Reading TBranch with leaf list


ROOT Version: v6.14.06
Platform: Ubuntu 16.04.6 LTS
Compiler: 5.4.0


I have a root file in which a branch was written as a leaf list instead of a full object. What is the best way to read a leaf list in this scenario? I had never done this until today, which is why I am asking here if what I am doing is the “standard” way.

Here is my minimal example that shows how I am currently reading the leaf list. Is there a better/safer way to do this in the function read_tree()?

#include <iostream>

#include "TFile.h"
#include "TLeaf.h"
#include "TTree.h"

struct Channel {
  double time = 0;
  double energy = 0;
};

void make_tree() {

  auto file = std::unique_ptr<TFile>{TFile::Open("output.root", "RECREATE")};
  auto tree = new TTree("tree", "");

  Channel channel;
  tree->Branch("channel", &channel, "channel.time/D:channel.energy/D");

  channel.time = 1;
  channel.energy = 10.123;
  tree->Fill();

  channel.time = 2;
  channel.energy = 20.987;
  tree->Fill();

  tree->Write();
  file->Close();

}

void read_tree() {

  auto file = std::unique_ptr<TFile>{TFile::Open("output.root", "READ")};
  auto tree = (TTree*) file->Get("tree");

  double time = 0;
  TLeaf* leaf_time = (TLeaf*) tree->GetListOfLeaves()->FindObject("channel.time");
  double energy = 0;
  TLeaf* leaf_energy = (TLeaf*) tree->GetListOfLeaves()->FindObject("channel.energy");

  for (int i = 0; i < tree->GetEntries(); ++i) {
    tree->GetEntry(i);
    std::cout << i << "\t"
  	      << leaf_time->GetValue() << "\t"
	      << leaf_energy->GetValue() << std::endl;
  }

}

For reference, I looked at the following before posting:

I think there is an extra “channel” in your leaflist:

tree->Branch("channel", &channel, "time/D:energy/D");

Then one option is to read back a Channel object:

  Channel channel;                                                                                                      
  tree->SetBranchAddress("channel", &channel);                                                                          
                                                                                                                        
  for (int i = 0; i < tree->GetEntries(); ++i) {                                                                        
    tree->GetEntry(i);                                                                                                  
    std::cout << i << "\t" << channel.time << "\t" << channel.energy << std::endl;                                                                                
  }                                        

Also note that for (int i = 0; i < tree->GetEntries(); ++i) { is probably much less efficient than const auto entries = tree->GetEntries(); for (int i = 0; i < entries; ++i) {.

Cheers,
Enrico