Derive Macro ReadFromTree

Source
#[derive(ReadFromTree)]
{
    // Attributes available to this derive:
    #[oxyroot]
}
Available on crate feature derive only.
Expand description

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

Derive macro in order to read struct data from TTree. Branch names and types are deduced from fields.

§Basic usage

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 */ });

§Nested structures

use oxyroot::{ReadFromTree, RootFile};

#[derive(ReadFromTree)]
struct NestedStruct {
    a: i32,     // will be read from branch "s.a" as 32 bits integer
    s: String,  // will be read from branch "s.s" as String
}

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

§Customisation

This macro can be customized with the following attributes:

  • By using attribute #[oxyroot(rename = "...")], it is possible to use different branch name:
use oxyroot::ReadFromTree;

#[derive(ReadFromTree)]
 struct MyStruct {
     #[oxyroot(rename = "b")]
     a: i32,     // will be read from branch *"b"* as 32 bits integer
     s: String,  // will be read from branch "s" as String
 }
  • By using attribute #[oxyroot(branch_prefix = "...")] directly on the struct, it is possible to globally (i.e. for all fields) prefix all branch names:
use oxyroot::ReadFromTree;

#[derive(ReadFromTree)]
#[oxyroot(branch_prefix = "branch_")]
 struct MyStruct {
     a: i32,     // will be read from branch *"branch_a"* as 32 bits integer
     s: String,  // will be read from branch *"branch_s"* as String
 }
  • By using attribute #[oxyroot(branch_prefix = "...")] on a field, it is possible to locally prefix branch name:
use oxyroot::ReadFromTree;

#[derive(ReadFromTree)]
 struct MyStruct {
     a: i32,     // will be read from branch *"a"* as 32 bits integer
    #[oxyroot(branch_prefix = "branch_")]
     s: String,  // will be read from branch *"branch_s"* as String
 }
  • By using attribute #[oxyroot(absolute_name = "...")] on a field, it is possible to precisely set the branch name, even in a nested struct:
use oxyroot::ReadFromTree;

#[derive(ReadFromTree)]
 struct MyStruct {
     a: i32,     // will be read from branch *"a"* as 32 bits integer
    #[oxyroot(absolute_name = "branch_s")]
     s: String,  // will be read from branch *"branch_s"* as String
 }
  • In combination with #[oxyroot(branch_prefix = "...")]:
use oxyroot::ReadFromTree;

#[derive(ReadFromTree)]
#[oxyroot(branch_prefix = "branch_")]
struct MyStruct {
   a: i32,     // will be read from branch *"branch_a"* as 32 bits integer
   c: f64,     // will be read from branch *"branch_c"* as 64 bits float
  #[oxyroot(absolute_name = "zweig_s")]
  s: String,  // will be read from branch *"zweig_s"* as String
}
  • Use #[oxyroot(slicable)] if the C++ class has a std::vector as a member.
use oxyroot::ReadFromTree;

#[derive(ReadFromTree)]
#[oxyroot(slicable)]
struct Point {
    x: i32, // will be read from branch "points.x" as 32 bits integer
    y: i32, // will be read from branch "points.y" as 32 bits integer
}

#[derive(ReadFromTree)]
struct SeveralPoints {
    #[oxyroot(slicable = "Point")]
    points: Vec<Point>, // will be read from branches "points.x" and "points.y" as a vector of
                        // Point
}

This combinaison can be used to read TTree created from C++ classes like:

class Point {
    public:
        int x = 0;
        int y = 0;
};
class SeveralPoints {
    public:
        std::vector<Point> points;
};

TTree *myTree = new TTree("myTree", "");
SeveralPoints tp;
for (int i = 0; i < 10; ++i)
{
    Point p;
    p.x = i;
    p.y = i*i;
    tp.points.push_back(p);
    myTree->Fill();
}