Get started#
Uproot-custom ships with built-in readers and factories that handle most common data types out of the box. This page walks you through the two key steps — registering a branch and reading it — so you can start working with your data right away.
Step 1: Obtain the object-path of a branch#
Uproot-custom identifies branches by their regularized object-path.
To find the path for a branch, open the file with Uproot and call
regularize_object_path:
import uproot
import uproot_custom as uc
f = uproot.open("file.root")
obj_path = f["my_tree/my_branch"].object_path
regularized_obj_path = uc.regularize_object_path(obj_path)
print(regularized_obj_path)
/my_tree:my_branch
Step 2: Register the branch and read#
Register the regularized path before opening the file. Uproot caches interpretations on first access, so late registration will have no effect.
import uproot
import uproot_custom as uc
uc.AsCustom.target_branches.add("/my_tree:my_branch")
f = uproot.open("file.root")
f["my_tree"].show()
Once the registration succeeds, the branch’s interpretation should display as
AsCustom:
Tip
uc.AsCustom.target_branches is a set. You can register several branches at
once:
uc.AsCustom.target_branches |= {"/my_tree:branch1", "/my_tree:branch2"}
Now read the data as you normally would with Uproot:
arr = f["my_tree/my_branch"].array() # read by uproot-custom
Tip
Keep the set of target branches minimal — only register the branches that uproot-custom should handle.
Example: uproot-custom vs Uproot#
The following example demonstrates a case that Uproot cannot handle on its own:
a c-style array of std::vector<double> stored inside a custom class.
class TCStyleArray : public TObject {
public:
std::vector<double> m_vec_double[3]{
{ 1.0, 2.0, 3.0 },
{ 4.0, 5.0, 6.0 },
{ 7.0, 8.0, 9.0 }
};
}
TTree t("my_tree", "my_tree");
TCStyleArray obj;
t.Branch("cstyle_array", &obj);
for (int i = 0; i < 10; i++) {
obj = TCStyleArray();
t.Fill();
}
import uproot
import uproot_custom as uc
uc.AsCustom.target_branches.add("/my_tree:cstyle_array/m_vec_double[3]")
f = uproot.open("file.root")
f["my_tree/cstyle_array/m_vec_double[3]"].array()
[[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]],
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]]
-------------------------------------
backend: cpu
nbytes: 1.1 kB
type: 10 * var * 3 * var * float64
Inspect the branch to confirm uproot-custom is active:
f["my_tree/cstyle_array/m_vec_double[3]"].show()
name | typename | interpretation
---------------------+--------------------------+-------------------------------
m_vec_double[3] | vector<double>[][3] | AsCustom(vector<double>[][3])
The interpretation AsCustom(vector<double>[][3]) confirms uproot-custom is
being used.
import uproot
f = uproot.open("file.root")
f["my_tree/cstyle_array/m_vec_double[3]"].array()
This raises a DeserializationError:
DeserializationError: expected 90 bytes but cursor moved by 34 bytes (through std::vector<double>)
in file file.root
in object /my_tree;1