PyROOT, TTree and empty complex type or empty pointer

Dear ROOTers,

I would like to fill a TTree with histograms in PyROOT. The problem is, that for a branch with histograms the type is inferred from an object, which is not fully set-up at the time of TTree creation. Thus the solution I came up with is:

t = ROOT.TTree("t", "t")
# The contents of a are not known at the moment
a = ROOT.TH1D()
t.Branch("h", a)
...
# The contents of the histogram are computed
b = ROOT.TH1D("b", "b", ...)
t.SetBranchAddress("h", b)
t.Fill()

Works, but the problem is, that first, we are creating a real object for an empty histogram, which is never used. I think in C++ I would just create an empty TH1D pointer and create a branch with it. However, I don’t think I can create an empty TH1D pointer in PyROOT. Is there a better way to do it in PyROOT? I know I can really use the initial histogram, resetting it before every Fill(), but since TH1 does not have a Set() function accepting the same parameters as the constructor (or am I wrong?), it does not seem very convenient.

Hello,

To avoid the creation of an empty histogram at the beginning, you can try:

a = ROOT.MakeNullPointer(ROOT.TH1D)

That creates a Python proxy for a TH1D object that points to null.

Thanks, works! It would be nice to have all those advanced PyROOT features documented somewhere someday :slight_smile:

Not directly related: reading TTrees is nicely pythonised. Writing not so much. I was wondering, if it wouldn’t be simple to add some pythonisations, for example that “=” operator on existing branch calls SetBranchAddress(), like:

tree.branch_name = some_variable

would be equal to:

tree.SetBranchAddress("branch_name", some_variable)

This seems easy, but perhaps I am not seeing any problems. A much more complex (and difficult to implement) version would be having two operators, perhaps “=” and “:=”, one of them setting branch address, the other just modifying the contents of the branch variable. The second case would require recognition to what the branch points, and in the case of an array, modifying [:] of an array.

Another complicated thing would be the creation of branches using “=” operator. At the moment one can do tree.new_attribute = “something”, but it will be just a string attribute. It would be nice if it could call Branch() instead.

I realise that these require work to implement, but just giving some ideas that I am thinking about dirty-implementing in my own scripts.

Thanks, works! It would be nice to have all those advanced PyROOT features documented somewhere someday :slight_smile:

It is actually documented here already :smiley:

Regarding the pythonization ideas for a layer on top of SetBranchAddress or Branch, I guess it could be done via some manipulation of __setattr__ in TBranch (probably together with some extra behaviour for TTree too). However, since we are focusing more on RDataFrame for TTree manipulation data (also in Python) I’d say we will put more effort on RDataFrame pythonizations. But if you’d like to contribute (and have time for it), new pythonizations are welcome!

https://root.cern/ideas/2020-06-26-add-a-root-pythonization/

I must have missed it somehow…

I’d gladly contribute, but, as everyone, I would need to find time :slight_smile: Anyway, the problem is that RDataFrame is, from what I understand, created with reding in mind. At least when I approached it, creating a new TTree and branches with it was far from straightforward and well documented. Maybe it has changed though.

You can also use RDataFrame to create new trees, usually with a combination of Defines to define new branches plus a final Snapshot to write the tree.

https://root.cern.ch/doc/master/df007__snapshot_8py.html

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