How to write aliases to a new tree?
Following the example here
import uproot
import numpy
with uproot.recreate("example.root") as f:
f["t"] = uproot.newtree({"branch": "int32"})
f["t"].extend({"branch": numpy.array([1, 2, 3, 4, 5])})
trying to do something like
myalias = uproot.rootio.TNamed()
myalias._classversion = 1
myalias._fName = b'small_R_jets_pt_0'
myalias._fTitle = b'pt_jet_1'
f["t"]._tree.fields['_fAliases'] = [myalias]
doesn't seem to be writing the aliases out.
EDIT: We do not currently support the user specifying attributes such as fAliases to be written. @jpivarski if we add this, is there any other attribute we should allow the user to specify?
Would it be possible for you (or @jpivarski ) to point me to a ROOT file having a TTree with fAliases set? The fAliases I have looked at have been TLists whereas in your example it is a TObjArray (or there is some gaps in my understanding of TList and TObjArray).
I'm not sure it's a bug. Was there ever an attempt to implement alias-writing? If we've never tried to do it and never tested it, that makes it "not implemented," not a bug.
There might be some files in tests/samples with aliases. I'm pretty sure CMSSW MiniAOD files have aliases (available in CERN's Open Data Portal), but that's going to a lot of effort.
Some of these other issues really are bugs, and they should take priority over new features.
Some of these other issues really are bugs, and they should take priority over new features.
I agree.
that makes it "not implemented," not a bug.
I suspect it just wasn't implemented. As for my use case -- being able to mimic CopyTree - this is the last piece. I'm working around this by actually expanding out the alias/evaluating it via numexpr + formulate and adding it into the new tree as an actual branch instead. This can make the file sizes bigger as aliases don't take up any size right now.
@reikdas - if you already have a ROOT file, there are two forms of aliases that would generally need to get handled by uproot (if Jim thinks it's worthy of adding). You can open the ROOT file in ROOT and do:
- simple alias that is evaluated and treated as a branch in uproot:
tree->SetAlias("simple_alias", "jet_pt_1") - complex (formula) alias that is not treated as a branch in uproot:
tree->SetAlias("complex_alias", "2*jet_pt_1 + jet_pt_2 + 10")
Aliases, are as I understand it, just fundamentally the name and a formula to evaluate. There's no check in ROOT to see if the alias evaluates successfully or not until the user runs it or tries to evaluate it.
So as for writing these two kinds into a ROOT file from uproot, they should be treated identically. They seem to load as TNamed which is why I did it the way I did in the code block in the issue.
It's worth adding, though we'd want to make it a __setitem__ type of interface, so that you don't need to remember the spelling (and capitalization!) of SetAlias.
It's worth adding, though we'd want to make it a
__setitem__type of interface, so that you don't need to remember the spelling (and capitalization!) ofSetAlias.
I've been stockholm-syndrome'd into using ROOT capitalization's scheme.
One other thing I forgot: aliases don't have dtypes (until evaluated). That might not be tricky to handle in a language like python...
In uproot, tree.aliases returns a dict from strings to strings. They're not interpreted as branches with types. There was some talk earlier about using formulate and NumExpr to make them act like branches by evaluating them on the branches that do exist, but that never happened. In our view of the world, aliases are still just string mappings.
In uproot,
tree.aliasesreturns a dict from strings to strings. They're not interpreted as branches with types.
Except for the simple ones, which get treated like branches.
Oh, right—early on, I misunderstood what aliases were (I thought they were just renaming branches, not formulas) and so a tree.__getitem__ first checks for real branch names then checks to see if an alias maps from what you asked for to a real branch name. Effectively, we can evaluate symbols that consists of no math.