Accessing TBranch Value

TTreeReaderValue<double> my_branch_value(reader "RUNID");
ROOT_prompt_2:1:49: error: expected ')'
TTreeReaderValue<double> my_branch_value(reader "RUNID");
                                                ^
ROOT_prompt_2:1:41: note: to match this '('
TTreeReaderValue<double> my_branch_value(reader "RUNID");
                                        ^
ROOT_prompt_2:1:26: error: no matching constructor for initialization of 'TTreeReaderValue<double>'
TTreeReaderValue<double> my_branch_value(reader "RUNID");
                         ^               ~~~~~~
/home/SJLPHI/Physics_Soft/ROOT6/include/ROOT/RDF/NodesUtils.hxx:21:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion
      from 'TTreeReader' to 'const TTreeReaderValue<double>' for 1st argument
class TTreeReaderValue;
      ^
/home/SJLPHI/Physics_Soft/ROOT6/include/ROOT/RDF/NodesUtils.hxx:21:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion
      from 'TTreeReader' to 'TTreeReaderValue<double>' for 1st argument
/home/SJLPHI/Physics_Soft/ROOT6/include/TTreeReaderValue.h:137:4: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
   TTreeReaderValue() = delete;
   ^
/home/SJLPHI/Physics_Soft/ROOT6/include/TTreeReaderValue.h:138:4: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
   TTreeReaderValue(TTreeReader& tr, const char* branchname):
   ^

Note that ROOT does not require that you use pointers to TFiles. I only point it out because it’s a common misunderstanding, there are certainly use-cases in which a pointer might be more appropriate.

Should be reader, "RUNID", I missed a comma when I typed things out.

EDIT: the compiler error message could be clearer, but you can see from the candidate signatures that the constructor takes two arguments

root [0] TFile file("image_4232_ext_1.root")
(TFile &) Name: image_4232_ext_1.root Title: 
root [1] TTreeReader reader("file_info" , &file)
(TTreeReader &) Name: TTreeReader Title: A simple interface to read trees
root [2] TTreeReaderValue<double> my_branch_value(reader ,"RUNID");
root [3] reader.SetEntry(42);
root [4] std::cout << *my_branch_value << std::endl;
Error in <TTreeReaderValue::Get()>: Value reader not properly initialized, did you remember to call TTreeReader.Set(Next)Entry()?

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007fe8a2398d9a in waitpid () from /lib64/libc.so.6
#1  0x00007fe8a231646f in do_system () from /lib64/libc.so.6
#2  0x00007fe8a34e219d in TUnixSystem::Exec (shellcmd=<optimized out>, this=0x17a07c0) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/unix/src/TUnixSystem.cxx:2119
#3  TUnixSystem::StackTrace (this=0x17a07c0) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/unix/src/TUnixSystem.cxx:2413
#4  0x00007fe8a34e49b4 in TUnixSystem::DispatchSignals (this=0x17a07c0, sig=kSigSegmentationViolation) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/unix/src/TUnixSystem.cxx:3644
#5  <signal handler called>
#6  0x00007fe8a3b4203e in ?? ()
#7  0x0000000001df8960 in ?? ()
#8  0x00007fe89e208978 in cling::MultiplexInterpreterCallbacks::EnteringUserCode() () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#9  0x00007ffde8479550 in ?? ()
#10 0x00007fe8a3b42000 in ?? ()
#11 0x00007fe89e20d0df in cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) [clone .part.310] () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#12 0x00007fe89e20d4ff in cling::Interpreter::EvaluateInternal(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::CompilationOptions, cling::Value*, cling::Transaction**, unsigned long) () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#13 0x00007fe89e20dc47 in cling::Interpreter::process(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::Value*, cling::Transaction**, bool) () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#14 0x00007fe89e2c59dd in cling::MetaProcessor::process(llvm::StringRef, cling::Interpreter::CompilationResult&, cling::Value*, bool) () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#15 0x00007fe89e16486e in HandleInterpreterException (metaProcessor=0x1df79c0, input_line=<optimized out>, compRes=
0x7ffde8479424: cling::Interpreter::kSuccess, result=result
entry=0x7ffde8479550) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/metacling/src/TCling.cxx:2163
#16 0x00007fe89e1775ed in TCling::ProcessLine (this=0x1812cd0, line=<optimized out>, error=0x7ffde847991c) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/metacling/src/TCling.cxx:2321
#17 0x00007fe8a33964ad in TApplication::ProcessLine (this=0x17fdb20, line=<optimized out>, sync=<optimized out>, err=0x7ffde847991c) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/base/src/TApplication.cxx:1031
#18 0x00007fe8a383a7a2 in TRint::ProcessLineNr (this=this
entry=0x17fdb20, filestem=filestem
entry=0x7fe8a384c3c5 "ROOT_prompt_", line=0x3117720 "std::cout << *my_branch_value << std::endl;", error=0x7ffde847991c, error
entry=0x0) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/rint/src/TRint.cxx:746
#19 0x00007fe8a383aaf4 in TRint::HandleTermInput (this=0x17fdb20) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/rint/src/TRint.cxx:607
#20 0x00007fe8a34e3ea8 in TUnixSystem::CheckDescriptors (this=this
entry=0x17a07c0) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/unix/src/TUnixSystem.cxx:1322
#21 0x00007fe8a34e5678 in TUnixSystem::DispatchOneEvent (this=0x17a07c0, pendingOnly=<optimized out>) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/unix/src/TUnixSystem.cxx:1077
#22 0x00007fe8a33ff581 in TSystem::InnerLoop (this=0x17a07c0) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/base/src/TSystem.cxx:412
#23 TSystem::Run (this=0x17a07c0) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/base/src/TSystem.cxx:362
#24 0x00007fe8a339456f in TApplication::Run (this=this
entry=0x17fdb20, retrn=retrn
entry=false) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/base/src/TApplication.cxx:1183
#25 0x00007fe8a383c046 in TRint::Run (this=this
entry=0x17fdb20, retrn=retrn
entry=false) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/rint/src/TRint.cxx:460
#26 0x000000000040098a in main (argc=<optimized out>, argv=0x7ffde847bd48) at /home/SJLPHI/Physics_Soft/source_packages/root6source/main/src/rmain.cxx:30
===========================================================


The lines below might hint at the cause of the crash.
You may get help by asking at the ROOT forum http://root.cern.ch/forum
Only if you are really convinced it is a bug in ROOT then please submit a
report at http://root.cern.ch/bugs Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#6  0x00007fe8a3b4203e in ?? ()
#7  0x0000000001df8960 in ?? ()
#8  0x00007fe89e208978 in cling::MultiplexInterpreterCallbacks::EnteringUserCode() () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#9  0x00007ffde8479550 in ?? ()
#10 0x00007fe8a3b42000 in ?? ()
#11 0x00007fe89e20d0df in cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) [clone .part.310] () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#12 0x00007fe89e20d4ff in cling::Interpreter::EvaluateInternal(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::CompilationOptions, cling::Value*, cling::Transaction**, unsigned long) () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#13 0x00007fe89e20dc47 in cling::Interpreter::process(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::Value*, cling::Transaction**, bool) () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#14 0x00007fe89e2c59dd in cling::MetaProcessor::process(llvm::StringRef, cling::Interpreter::CompilationResult&, cling::Value*, bool) () from /home/SJLPHI/Physics_Soft/ROOT6/lib/libCling.so
#15 0x00007fe89e16486e in HandleInterpreterException (metaProcessor=0x1df79c0, input_line=<optimized out>, compRes=
0x7ffde8479424: cling::Interpreter::kSuccess, result=result
entry=0x7ffde8479550) at /home/SJLPHI/Physics_Soft/source_packages/root6source/core/metacling/src/TCling.cxx:2163
===========================================================


This is because I memory allocate the file size.

My best guess is that your TTree has less than 42 entries.

Yes, there are 17, and I tried setting entry to 42, same segment fault.

With 17 entries, reader.SetEntry(42) is bound to fail. Valid entry numbers are in the range 0 to 16 inclusive.
As per the doc, you can check wheter a SetEntry call succeded by inspecting its return value.

It did not fail at SetEntry, it failed at cout for the value.

You will get a segfault when accessing the value if SetEntry failed.
SetEntry signal failures through its return value.
Anyway, if your TTree has 17 entries, reader.SetEntry(42) will always return an error.

By the way, with RDataFrame your ifstream example becomes:

ROOT::RDataFrame("my_tree", "my_file.root").Foreach([](double x) { std::cout << x << std::endl; }, {"my_branch"});

or

ROOT::RDataFrame("my_tree", "my_file.root").Display("my_branch")->Print();

Unfortunately I cannot access my files. I can still see them just fine in TBrowser, but not using the TTreeReader.
I have already embeded the “file_info” into the root file. I just want to read it out into a variable.

Can this be achieved using RDataFrame?

Hi,

what’s the issue?


Yes, for example you can get all the contents of a TTree branch in a std::vector with RDataFrame’s Take (haven’t tested the code, might contain typos):

std::vector<double> values = ROOT::RDataFrame("my_tree", "my_file.root").Take<double>("my_double_branch")->GetValue();

Cheers,
Enrico

My TFile has TTree called “file_info” which has a branch “RUNID” for an example.
From the TBrowser, I can see that RUNID has a value of 4232, which is what was appropriate.
From other methods it reads either 0, 1, 4 or 90000

The branch is NOT a vector. It is a single value.

I appreciate your help, but I come from a software development badkground, and I feel that I cannot progress without an accurate documentation on the object “tree”, “branches”, and believe me I read them both, and none of the getters can actually return the value that I have embeded from

TTree* file_info = new TTree(“file_info”,“file_info”);
file_info->Branch( keywords[i].c_str() , &headerlist[i] ,“Value/F” );

For example, when I use the print function of the tree I get this:

->Print()
******************************************************************************
*Tree    :file_info : file_info                                              *
*Entries :        1 : Total =           10125 bytes  File  Size =       2357 *
*        :          : Tree compression factor =   1.00                       *
******************************************************************************
*Br    0 :RUNID     : Value/F                                                *
*Entries :        1 : Total  Size=        566 bytes  File Size  =         81 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*

In first approximation, and especially for your current usecase, you can think of a TTree as a table.
Branches are columns of the table, entries are rows.

When creating/writing a TTree, every call to TTree::Branch will create a new column, and every call to TTree::Fill will add a new row. The values that are used to fill each column for each row are read from the addresses that are associated to the columns by the TTree::Branch call.

For example:

float value = 0.f;
tree->Branch("value", &value);
tree->Fill();
value = 8.f;
tree->Fill();

creates a column with name "value" which will have two rows, one with value 0 and one with value 8.

That’s why RDataFrame’s Take returns a vector: typically you have more than one value per branch. If you have only one value, you can retrieve it as the first and only element of the vector.

As to why the values that you read back are wrong, I don’t know, there is a problem somewhere in your code. Maybe it’s the extra "Value/F" argument to TTree::Branch that makes it trickier to retrieve the correct values later.

Here is a working snippet that creates a TTree called "file_info" in a file "f.root", writes one entry of branch "RUNID" and then reads it back with raw TTree, TTreeReader and RDataFrame.

#include <TTree.h>
#include <TFile.h>
#include <TTreeReader.h>
#include <TTreeReaderValue.h>
#include <ROOT/RDataFrame.hxx>
#include <vector>
#include <cassert>

void write_tree()
{
   TFile f("f.root", "recreate");
   TTree t("file_info", "file_info");
   float value = 42.f;
   t.Branch("RUNID", &value);
   t.Fill();
   f.Write();
   f.Close();
}

float read_value_with_tree()
{
   TFile f("f.root");
   TTree *t = nullptr;
   f.GetObject("file_info", t);
   float value;
   t->SetBranchAddress("RUNID", &value);
   t->GetEntry(0);
   return value;
}

float read_value_with_treereader()
{
   TFile f("f.root");
   TTreeReader r("file_info", &f);
   TTreeReaderValue<float> v(r, "RUNID");
   r.SetEntry(0); // should check ret value to be sure reading succeded
   return *v;
}

float read_value_with_rdf()
{
   ROOT::RDataFrame df("file_info", "f.root");
   const std::vector<float> all_v = df.Take<float>("RUNID").GetValue();
   return all_v[0];
}

int main()
{
   write_tree();
   assert(read_value_with_tree() == 42.f);
   assert(read_value_with_treereader() == 42.f);
   assert(read_value_with_rdf() == 42.f);
   return 0;
}
1 Like

Okay, Excellent. This is the solution that I was looking for. I guess the point I was missing all this time is that the tree pointer address.
Thank you Enrico!

As a note, I don’t suggest using TTree directly to read ROOT data, it’s a low-level API, gives very few (type) safety guarantees, performs very few sanity checks and it’s also trickier to get good performance out of it. None of this might matter for this specific application of yours, but habits do matter :smile:

Given a branch created with file_info->Branch("RUNID", &some_float_var ,“Value/F” ); I can read it with

TFile f("f.root");
TTreeReader r("file_info", &f);
TTreeReaderValue<float> v(r, "RUNID.Value");
r.SetEntry(0);
std::cout << *v << std::endl;

I will also try and test the TTreeReader. For my specific application, I am basically handling everything in RAM and I have written a few upper level safety mechanisms such that if returning value isn’t very nice, I exit(0) or return from the function on the spot with an error message.

In the analysis that I am dealing with, the input file is rather large and read/write is only done in the beginning and and the end, and I hard-mallocate/free.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.