···1011 up_start_time = time.time()
12 up_tree = uproot.open(file_name)[tree_name]
13- for branch in up_tree.keys():
14- # print(branch, up_tree[branch].typename)
15- if up_tree[branch].typename != "std::string":
16- up_values = up_tree[branch].array(library="np")
17- print(f"Uproot read {branch} into a {type(up_values)} and it has a mean of {np.nanmean(up_values):.2f}")
18 up_end_time = time.time()
1920 print("\n")
2122 oxy_start_time = time.time()
23- oxy_branches = oxyroot.read_root(file_name, tree_name=tree_name)
24- for branch in oxy_branches:
25- oxyroot.read_root(file_name, tree_name=tree_name, branch=branch)
26- oxy_values = oxyroot.read_root(file_name, tree_name=tree_name, branch=branch)
027 if type(oxy_values) is np.ndarray:
28- print(f"Oxyroot read {branch} into a {type(oxy_values)} and it has a mean of {np.nanmean(oxy_values):.2f}")
29 else:
30- print(f"Oxyroot read {branch} into a {type(oxy_values)} and it has a length of {len(oxy_values)}")
31 oxy_end_time = time.time()
3233 print("\n Total time")
···1011 up_start_time = time.time()
12 up_tree = uproot.open(file_name)[tree_name]
13+ for branch in up_tree:
14+ # print(branch, branch.typename)
15+ if branch.typename != "std::string": # Uproot cannot read strings?
16+ up_values = branch.array(library="np")
17+ print(f"Uproot read {branch.name} into a {type(up_values)} and it has a mean of {np.nanmean(up_values):.2f}")
18 up_end_time = time.time()
1920 print("\n")
2122 oxy_start_time = time.time()
23+ oxy_tree = oxyroot.open(file_name)[tree_name]
24+ for branch in oxy_tree:
25+ # print(branch, branch.typename)
26+ # if branch.typename != "string":
27+ oxy_values = branch.array()
28 if type(oxy_values) is np.ndarray:
29+ print(f"Oxyroot read {branch.name} into a {type(oxy_values)} and it has a mean of {np.nanmean(oxy_values):.2f}")
30 else:
31+ print(f"Oxyroot read {branch.name} into a {type(oxy_values)} and it has a length of {len(oxy_values)}")
32 oxy_end_time = time.time()
3334 print("\n Total time")
+3-2
python/tests/test_read_from_uproot.py
···1-import pytest
2import oxyroot
3import uproot
4import numpy as np
5import os
0067def test_read_from_uproot():
8 # Create a dummy ROOT file for testing
···15 f["tree1"].extend({"branch1": input})
161718- output = oxyroot.read_root(file_name, tree_name="tree1", branch="branch1")
19 assert(type(output) is np.ndarray)
20 assert(np.array_equal(input, output))
21
···01import oxyroot
2import uproot
3import numpy as np
4import os
5+6+print(oxyroot.__version__)
78def test_read_from_uproot():
9 # Create a dummy ROOT file for testing
···16 f["tree1"].extend({"branch1": input})
171819+ output = oxyroot.open(file_name)["tree1"]["branch1"].array()
20 assert(type(output) is np.ndarray)
21 assert(np.array_equal(input, output))
22
+194-87
src/lib.rs
···1use ::oxyroot::{Named, RootFile};
2-use numpy::ToPyArray;
3-use pyo3::{exceptions::PyValueError, prelude::*, types::PyModule, IntoPyObjectExt};
000000000000000000000000000000000000000000000000000000000000000000045-#[pyfunction]
6-fn version() -> PyResult<String> {
7- Ok(env!("CARGO_PKG_VERSION").to_string())
000000008}
910-/// Read a ROOT file and return the list of trees, the branches of a tree, or the values of a branch.
11-#[pyfunction]
12-#[pyo3(signature = (path, tree_name = None, branch = None))]
13-fn read_root(
14 path: String,
15- tree_name: Option<String>,
16- branch: Option<String>,
17-) -> PyResult<Py<PyAny>> {
18- let mut file = RootFile::open(&path).unwrap();
19- let keys: Vec<String> = file
20- .keys()
21- .into_iter()
22- .map(|k| k.name().to_string())
23- .collect();
2425- Python::attach(|py| -> PyResult<Py<PyAny>> {
26- match tree_name {
27- Some(name) => {
28- if let Ok(tree) = file.get_tree(&name) {
29- let branches_available: Vec<String> =
30- tree.branches().map(|b| b.name().to_string()).collect();
000000000000000000003132- match branch {
33- Some(bs) => {
34- if let Some(branch) = tree.branch(&bs) {
35- match branch.item_type_name().as_str() {
36- "f32" => {
37- let data =
38- branch.as_iter::<f32>().unwrap().collect::<Vec<_>>();
39- Ok(data.to_pyarray(py).into_py_any(py).unwrap())
40- }
41- "double" => {
42- let data =
43- branch.as_iter::<f64>().unwrap().collect::<Vec<_>>();
44- Ok(data.to_pyarray(py).into_py_any(py).unwrap())
45- }
46- "int32_t" => {
47- let data =
48- branch.as_iter::<i32>().unwrap().collect::<Vec<_>>();
49- Ok(data.to_pyarray(py).into_py_any(py).unwrap())
50- }
51- "int64_t" => {
52- let data =
53- branch.as_iter::<i64>().unwrap().collect::<Vec<_>>();
54- Ok(data.to_pyarray(py).into_py_any(py).unwrap())
55- }
56- "uint32_t" => {
57- let data =
58- branch.as_iter::<u32>().unwrap().collect::<Vec<_>>();
59- Ok(data.to_pyarray(py).into_py_any(py).unwrap())
60- }
61- "uint64_t" => {
62- let data =
63- branch.as_iter::<u64>().unwrap().collect::<Vec<_>>();
64- Ok(data.to_pyarray(py).into_py_any(py).unwrap())
65- }
66- "string" => {
67- let data =
68- branch.as_iter::<String>().unwrap().collect::<Vec<_>>();
69- Ok(data.into_py_any(py).unwrap())
70- }
71- other => Err(PyValueError::new_err(format!(
72- "Unsupported branch type: {}",
73- other
74- ))),
75- }
76- } else {
77- Err(PyValueError::new_err(format!(
78- "Branch '{}' not found. Available branches are: {:?}",
79- bs, branches_available
80- )))
81- }
82- }
83- None => Ok(branches_available.into_py_any(py).unwrap()),
84- }
85- } else {
86- Err(PyValueError::new_err(format!(
87- "Tree '{}' not found. Available trees are: {:?}",
88- name, keys
89- )))
90- }
91 }
92- None => Ok(keys.into_py_any(py).unwrap()),
0000000000000000000000000000000000000093 }
94- })
0000000000000000000000095}
9697-/// A Python module to read root files implemented in Rust.
98#[pymodule]
99fn oxyroot(m: &Bound<'_, PyModule>) -> PyResult<()> {
100 m.add_function(wrap_pyfunction!(version, m)?)?;
101- m.add_function(wrap_pyfunction!(read_root, m)?)?;
0000102 Ok(())
103}