How to print (& fill histogram with) two branches that are array using TTreeReaderArray

Hello all.

This topic is related to TTreeReaderArray.
The goal is to print out the values inside the branches (array) in the terminal.
I have branch “energy” and “time” as shown below.

root [19] OutputTree->Scan("det.energy_:det.time_","","",1000,78400)
***********************************************
*    Row   * Instance * det.energy_ * det.time_ *
***********************************************
*    78400 *        0 * 37.700216 * 1036.4219 *
*    78400 *        1 * 85.110013 * 1098.5080 *
*    78400 *        2 * 98.487813 * 1084.2928 *
*    78401 *        0 *           *           *
*    78402 *        0 * 72.195859 * 1036.3751 *
*    78402 *        1 * 35.378058 * 1084.2728 *
*    78402 *        2 * 56.932710 * 1107.9885 *
*    78402 *        3 * 39.948852 * 1074.6173 *
*    78403 *        0 *           *           *
*    78404 *        0 *           *           *
*    78405 *        0 *  103.0197 * -8.450341 *
*    78406 *        0 * 33.523407 * 1080.3913 *
*    78406 *        1 * 45.087502 * -0.422100 *
*    78406 *        2 * 56.645979 * 1099.3365 *
*    78407 *        0 * 11.311819 * 1081.0858 *
*    78408 *        0 *           *           *
*    78409 *        0 * 37.983352 * 1080.3177 *
*    78409 *        1 * 39.554136 * 1084.2923 *
*    78410 *        0 *           *           *

I access these branches using the TTreeReaderArray using the following code:

auto f = TFile::Open(filename);
TTreeReader r("OutputTree", f);
TTreeReaderArray<Double_t> v(r, "det.energy_");
TTreeReaderArray<Double_t> w(r, "det.time_");

while (r.Next()) 
{
for (auto &m : v)
printf("The energy is: %f\n", m);
}

//**How to print out the energy and time values together?**
//for (auto &n : w)    //time
//printf("The energy is: %f, the time is %f\n", m, n);

With the above line of code, I can successfully print out all the instances (array element) for the ‘energy’ branch as shown below:

The energy is: 37.700216
The energy is: 85.110013
The energy is: 98.487814
The energy is: 72.195860
The energy is: 35.378058
The energy is: 56.932710
The energy is: 39.948853
The energy is: 103.019700
The energy is: 33.523407
The energy is: 45.087503
The energy is: 56.645979
The energy is: 11.311820
The energy is: 37.983352
The energy is: 39.554136

Question: How can I print the values of the ‘time’ branch corresponding to the energy value?
That is I am looking to print in the following manner:

The energy is: 37.700216, the time is 1036.4219
The energy is: 85.110013, the time is 1098.5080
The energy is: 98.487814, the time is 1084.2928
The energy is: 72.195860, the time is 1036.3751
The energy is: 35.378058, the time is 1084.2728
The energy is: 56.932710, the time is 1107.9885
The energy is: 39.948853, the time is 1074.6173
The energy is: 103.019700, the time is -8.450341
The energy is: 33.523407, the time is 1080.3913
The energy is: 45.087503, the time is -0.422100
The energy is: 56.645979, the time is 1099.3365
The energy is: 11.311820, the time is 1081.0858
The energy is: 37.983352, the time is 1080.3177
The energy is: 39.554136, the time is 1084.2923

The final aim is to make (fill) a 2D histogram with these two branch values. How can I do it?
Also, if the same is possible with the RDataFrame, please guide on that too if possible.

ROOT Version: 6.26/10
Platform: Ubuntu 22.04.2 LTS

Thank you!

If they are the same size, you can simply do something like this:

for (auto i=0; i < v.GetSize(); ++i) {
   printf("The energy is: %f, the time is: %f\n", v[i], w[i]);
}
for (auto i=0; i < v.GetSize(); ++i) {
   h2->Fill(v[i], w[i]);
}

I’ll let @vpadulan give details for RDataFrame. Maybe something like:

auto file = TFile::Open(filename);
auto tree = file->Get<TTree>(treename);
ROOT::RDataFrame rdf(treename, filename);
auto h2 = rdf.Histo2D({"h2", "energy vs time", 100, 0., 100., 100, 0., 2000.}, "det.energy_", "det.time_");

(you can take a look at the RDataFrame tutorials)

1 Like

Thanks for the reply.

Yes, they have the same size.
Doing the above as recommended leads to: *** Break *** segmentation violation

Can you provide a minimal reproducer?

Sorry, I will have to make a minimal reproducer. As and when I make it, I will post it.
Thanks.

That’s usually an index out of range, like when the arrays are not the same size. So, add a check comparing the two sizes and print out (before the loop with printf("The energy is: %f, the time is: %f\n", v[i], w[i]) if they are different, you should see that message before the seg fault.

1 Like

Thanks for the reply.

I print the size with this:

#include <iostream>
#include <TTree.h>
#include <TFile.h>
#include <TTreeReader.h>
#include <TTreeReaderValue.h>
#include <TTreeReaderArray.h>

using namespace std;
void getsize()
{
auto f = TFile::Open("file.root");
TTreeReader r("OutputTree", f);
TTreeReaderArray<Double_t> v(r, "det.energy_");
TTreeReaderArray<Double_t> w(r, "det.time_");

   auto vsize = v.GetSize();
   auto wsize = w.GetSize();
   printf("v size is: %lu and w size is: %lu\n", vsize, wsize);

}

int main()
{
   getsize();
   return 0;
}

This also throws Seg fault.

You have to be inside the loop over r, of course; otherwise, how are you going to get any v or w?

1 Like

My mistake!

while(r.Next()){
           auto vsize = v.GetSize();
           auto wsize = w.GetSize();
           printf("v size is: %lu and w size is: %lu\n", vsize, wsize);}

This do return the same size for v and w!

Are you 100% sure? Do not check by eye, make the differences in the code and print a special message if they are different. If all are indeed equal, then continue as bellenot suggested.

1 Like

Thanks for the reply.
The Seg fault was due to the ‘not looping over r’. As suggested by you, I included it.
Now, Bellenot’s suggested lines work!

Thanks for the help!

1 Like