Calling variables of TTree in PyROOT by branch name

Hello,

For a long time, maybe improperly, I was using TTrees with variables refering to the branches names, not leafs names (usually I have one leaf per variable). This is working with TTree::Draw() and Scan() in ROOT and PyROOT. It was also working directly in PyROOT referring to tree.branchname. However, it seems it stopped, or stops in some cases in ROOT >5.34.15. I use .15 on my computer and the info that it does not work comes from other people with higher versions.

Now, when referring to a branch name one gets:

Is it how it is supposed to be, Scan() and Draw() just still supporting a wrong approach? Or was there a bug introduced in more recent ROOTs?

Anyway, if one wants to try, here is a sample file:
copy.com/ekSfyq9Ht7kIUzJ8

Just try, for example, in python shell:

import ROOT
f = ROOT.TFile("crash_file.root", "read")
t = f.Get("tevent")
t.cpu_packet_time

On new ROOT versions it should display the error message.
[/code]

Hi,

thanks for reporting.
I can indeed reproduce this with 5.34. The 6 versions, both 6.03 and 6.02 work. We’ll follow up this item.

Cheers,
Danilo

Exists on 5.34.19 and up (not sure if exactly in the same way), so was probably introduced between 5.34.15 and 5.34.19. Hope this helps.

I’d really appreciate a workaround - currently people with slightly newer ROOT cannot use my software :frowning:

Hi,

a workaround would be to create the object of the right type, use SetBranchAddress, then assign it to the tree. Quick ‘pseudo-code’:t = f.tevent cpu_packet_time = CpuPacketTime() t.SetBranchAddress("cpu_packet_time", cpu_packet_time) t.cpu_packet_time = cpu_packet_time
Since the TypeError is a python exception, you can also do the above in a custom getattr for TTree, if you do not know a priori the types.

Sorry about that.

Cheers,
Wim

My types are only basic types, but still, I understand that I have to enter code that makes a buffer from some arrays, while only a ROOT.int from and int, etc. if I don’t know a priori the types?

Hi,

how was this file created? Basic types show up as leaves, not branches. But this tree only has a branch cpu_packet_time, which of course has no class name (hence the error)?

Cheers,
Wim

So the branches are created like:

tevent->Branch("cpu_packet_time",&Packet.time,"time/I");

where Packet is a proper structure. Then writing has a few cases, but in general it is something like that:

f = new TFile(filename.c_str(), mode.c_str());
		tevent->SetDirectory(f);
		tevent->Write("", TObject::kWriteDelete);
tevent->SetDirectory(0);
f->Close();

The branch does not has class name, but somehow it was recognized in PyROOT for ROOT 5.34.15 and works without problem with TTree::Draw() and Scan()…

Hi,

okay, got it: there’s no named leaf, but then there is only one leaf, so the code may assume that that’s got to be the one. Will apply. But it also suggests another workaround: simply name the leaf:t.GetBranch("cpu_packet_time").GetListOfLeaves().At(0).SetName("cpu_packet_time")
Cheers,
Wim

Actually, putting that wrong: there’s no leaf named “cpu_packet_time”. The leaf does have a name, of course, but it is “time” (per the “time/I” part when creating the branch). And yes, t.time does give the proper result.

Cheers,
Wim

OK, the last fix (without testing yet) seems easy to automatize - check if there is only one leaf in the branch, if yes than rename it to the name of the branch.

Still, I did not understand - is it a bug that was introduced after ROOT 5.34.15, or a feature? :slight_smile:

Dunno … haven’t done any digging. In fact, I was surprised to see that the code did work in ROOT6, which has the same pythonization code. Still, I applied the patch there as well as it doesn’t hurt.

Cheers,
Wim

Is the patch in recent ROOT 5 versions? I could not find it in the patch release notes…

Hi,

should be in any patch release after the data on the posting above. Sorry, I’m spread over too many projects to know, let alone follow, details on release notes, etc.

Cheers,
Wim