PyRoot TTree -add double array in single entry

Hi ROOT experts,

I have a problem regarding root trees through PyRoot.

I have created 3 branches which correspond to 3 numpy arrays with approximately 85 values in it. I am looping through a folder of files and I am hoping that I am able to put an array of values to represent individual leaf of the branch. In other words, each individual file has a single array of values in a branch call. The total number of entries should be the number of files in the tree rather than each individual datapoint.

How do I do this?

The code currently has problems where there are 30 entries as expected. However, inside the entry branches, each branch returns a singular value with each value being 0 rather than an entire array.

f = ROOT.TFile("tree.root", "recreate")
t = ROOT.TTree( 't1', 'tree with histos' )

//I created a structure to reference as a memory address which may be a mistake?
ROOT.gROOT.ProcessLine(
"struct tc_t {\
   Double_t var_vol;\
   Double_t var_time;\
   Int_t var_res;\
}" )
tc = ROOT.tc_t()

//Loop through the files
for i in range(files_total):
           ... Prior calculations on file
          ........................................


            //Below, the second parameters of np_time_values and np_voltage_values are numpy python arrays of type float and type int for resistance_value_i

            time_values_c = array.array('d', np_time_values )
            voltage_values_c = array.array('d', np_voltage_values)
            resistance_value_i_c = array.array('i', resistance_value_i)
            
            //The below prints confirmed the arrays were returning values I expected i.e. ~85 values of unique values or repeating in case of resistance_values 
            print run_count
            print time_values_c
            print voltage_values_c
            print resistance_value_i_c
            
            t.Branch('time_values',time_values_c,'time_values/D')
            t.Branch('voltage_values',voltage_values_c,'voltage_values/D')
            t.Branch('resistance_values',resistance_value_i_c,'resistance_values/I')
 
            t.SetBranchAddress("voltage_values",ROOT.AddressOf(tc, 'var_vol'))
            t.SetBranchAddress("time_values",ROOT.AddressOf(tc, 'var_time'))
            t.SetBranchAddress("resistance_values",ROOT.AddressOf(tc, 'var_res'))
            
            t.Fill()

............ End of File Loop

     f.Write()
     f.Fill()

Below is the code I am running


Thanks!
Aaron

Hi Aaron,

so you have N*3 files, each containing an array. You would like to have a TTree with N entries and 3 branches therefore storing for each entry 3 arrays, which come from 3 different files. Is this correct?

Cheers,
D

Hi D,

I have a subjective amount of files I’m looping through in a folder.
Each File has around ~85 data points in an array. Each individual branch entry I am hoping for it to be an array such that I can access each entry as an individual array. There are 3 branches for each file representing voltages, times, and resistances that should correlate to each other as an individual file.

In more clarity, if I have 90 files in the folder, I hope to have 90 entries where each entry (individual file) has 3 branches of voltages, times, and resistances and is condensed into a single array. If I call t->GetEntry(0), I hope to be able to call an array out of it in C++ using a format similar to as follows:

TFile f(“tree.root”);
TTree t = (TTree)f.Get(“t1”);
Int_t n_data_points_total = (Int_t)t->GetEntries();

Double_t* Voltage = new Double_t[n_data_points_total];
Double_t* Time_ = new Double_t[n_data_points_total];
Double_t* Resistance = new Double_t[n_data_points_total];

Double_t var_vol, var_time;
Int_t var_res;

// t->SetBranchAddress(“voltage_values”,&var_vol);
// t->SetBranchAddress(“time_values”,&var_time);
// t->SetBranchAddress(“resistance_values”,&var_res);

for (Int_t i=0; i < t->GetEntries(); i++)
{
t->GetEntry(i);
Voltage[i] = var_vol;
Time_[i] = var_time;
Resistance[i] = var_res;
}
In the above code, I would hope that Voltage[0], Resistance[0], Time_[0] are all arrays of values that correlate with the first file, the second file correlates with an array in Voltage[1], Resistance[1], Time_[1], etc.

There are not 3 files as I am looping through a folder of N size to get through. There are 3 branches but an N amount of entries.

I apologize for not being clear in my initial statement. Let me know if I am still being unclear.

Thanks!
Aaron

Hi Aaron, What you need then is to have 3 arrays for each TTree entry (one per file in the directory). I have changed a bit the PyROOT code to achieve it.

import ROOT
import numpy as np
import array

f = ROOT.TFile("tree.root", "recreate")
t = ROOT.TTree( 't1', 'tree with vectors' )

ROOT.gInterpreter.ProcessLine("""
struct tc_t {
   std::vector<Double_t> var_vol {30};
   std::vector<Double_t> var_time {30};
   std::vector<Int_t> var_res {30};
   void set_vol(Double_t* v, size_t len) {var_vol.assign(v,v+len);}
   void set_time(Double_t* v, size_t len) {var_time.assign(v,v+len);}
   void set_res(Int_t* v, size_t len) {var_res.assign(v,v+len);}
};
""" )
tc = ROOT.tc_t()

t.Branch('values',tc)
files_total = 10

#---Loop through the files
for i in range(files_total):

  #---Get the np arrays from somewhere...
  np_time_values = np.linspace(0.,100.,30)
  np_voltage_values = np.fromfunction(lambda i: i * i, (30,))
  np_resistance_values = array.array('i',np.ones(30,dtype=int))  # Cannot use np arrays of 'integers' directly. It is bug :-()

  print np_time_values
  print np_voltage_values
  print np_resistance_values

  tc.set_vol(np_voltage_values, len(np_voltage_values))
  tc.set_time(np_time_values, len(np_time_values))
  tc.set_res(np_resistance_values, len(np_resistance_values))

  t.Fill()

t.Write()

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