Crate oxyroot

source ·
Expand description

This crate aims to provide a way to open and write data in ROOT file format and particularly Tree and Branch inside Tree. This crate is in fact a port of groot written in Go and uproot written in Python.

To read from a branch and write to a branch, the API is iterator based :

  • by branch:
    • as_iter to read from a branch. The type to read is provided as a type parameter. This type has to implement Unmarshaler trait.
    • new_branch from WriterTree to write to a branch. The method write from WriterTree is used to write the data to the file by exhausting provided iterators. The type to write has to implement Marshaler trait. The type is deduced from the iterator.
  • by Tree, by creating struct from several branches, thanks to the ReadFromTree and WriteToTree traits. These traits can be automatically derived with the derive feature which provides macros ReadFromTree and WriteToTree.

§Example: Iter over a branch tree containing i32 values

use oxyroot::RootFile;
let s = "examples/from_uproot/data/simple.root";
let tree = RootFile::open(s).expect("Can not open file").get_tree("tree").unwrap();
let one = tree.branch("one").unwrap().as_iter::<i32>().expect("wrong type");
one.for_each(|v| println!("v = {v}"));

§Example : Read custom struct from branches

use oxyroot::{ReadFromTree, RootFile};

#[derive(ReadFromTree)]
struct MyStruct {
     a: i32,     // will be read from branch "a" as 32 bits integer
     s: String,  // will be read from branch "s" as String
}
let tree = RootFile::open("in.root").unwrap().get_tree("tree").unwrap();
MyStruct::from_tree(&tree).unwrap().map(|m: MyStruct | {  /* do something with m */ });

More information and examples here : ReadFromTree

§Example: Show branches from a tree

use oxyroot::RootFile;
let s = "examples/from_uproot/data/simple.root";
let tree = RootFile::open(s).expect("Can not open file").get_tree("tree").unwrap();
tree.show();

will display

name                           | typename                       | interpretation
-------------------------------+-------------------------------+-------------------------------
one                            | int32_t                        | i32
two                            | float                          | f32
three                          | char*                          | String

§Example: Write i32 values in a branch

use oxyroot::{RootFile, WriterTree};
let s = "/tmp/simple.root";
let mut file = RootFile::create(s).expect("Can not create file");
let mut tree = WriterTree::new("mytree");
let it = (0..15);
tree.new_branch("it", it);
tree.write(&mut file).expect("Can not write tree");
file.close().expect("Can not close file");

§Example: Iter over a branch tree containing Vec<i32> (aka std::vector<int32_t>) values

use oxyroot::RootFile;
let s = "tests/stl_containers/stl_containers.root";
let tree = RootFile::open(s).expect("Can not open file").get_tree("tree").unwrap();
let vector_int32 = tree.branch("vector_int32")
                   .unwrap().as_iter::<Vec<i32>>().expect("wrong type")
                   .collect::<Vec<_>>();
assert_eq!(
    vector_int32,
    [
        vec![1],
        vec![1, 2],
        vec![1, 2, 3],
        vec![1, 2, 3, 4],
        vec![1, 2, 3, 4, 5]
    ]
);

§Which types can be read from a branch?

§Primitives and C++ STL standards

oxyroot can iterate over branch which contains :

  • primitive types like i32, f64, bool…
  • String (from TString, char* or std::string)
  • Vec (from std::vector or array)
  • HashMap
C++Rust
std::stringString
std::vectorVec
std::mapHashMap
std::setHashSet
T*Slice<T>
T[N]array
TStringString

Examples can be found in tests.

§Structures

Structure serialized in Branch can be also read but the parsing code has to be written :

struct sd_t {
         Int_t a;
         Int_t b;
};

sd_t sd;
tree->Branch("v_i",&sd, 3200000, 0);

The sd struct can be read with a code like this :

use oxyroot::RBuffer;
use oxyroot::RootFile;
struct Sd {
    a: i32,
    b: i32,
};

let parse = |r: &mut RBuffer| Sd {
    a: r.read_i32().unwrap(),
    b: r.read_i32().unwrap(),
};


let s = "tests_data/doc/struct_sd.root";
let tree = RootFile::open(s).expect("Can not open file").get_tree("T").unwrap();

// branch v_i contains v_i which will be zipped.
let mut b = tree.branch("v_i").unwrap().get_basket(parse);

for i in -10..10 {
    let sd = b.next().unwrap();
}

§Which types can be written to a branch?

§Primitives and C++ STL standards

oxyroot can iterate over branch which contains :

  • primitive types like i32, f64, bool…
  • String (will appear as a char*)
  • Vec (to std::vector)
  • HashMap (not yet implemented)

Modules§

Macros§

Structs§

Enums§

Traits§

Type Aliases§

Derive Macros§

  • Derive macro available if oxyroot is built with features = ["derive"].
  • Derive macro available if oxyroot is built with features = ["derive"].