How to read an arbitrary tree filled by vectors?

Dear root experts,

I would like to read an arbitrary tree in which the variables are std::vector of doubles. (aiming at filling another tree w.r.t some criteria…). The makeClass approach was ok to do this, but now I would like to transpose it within a piece of standalone C++ compiled code.

The relevant piece that I have written contains (it is supposed to “eat” a tree named ‘signal_in’)

TTree *Tree_out = new TTree;
const Long_t basketsize = 128000;
Int_t nvar = signal_in->GetNbranches();   
  
std::vector<Double_t> * varD = new std::vector<Double_t> [nvar];
Float_t* var_out = new Float_t[nvar];
Int_t i = 0;   
TIter follow_branch( signal_in->GetListOfBranches() ); 
 while (TBranch *branch = (TBranch*)follow_branch())
{
const char* myVar = branch->GetName();
signal_in->SetBranchAddress(myVar, &varD[i++]);
Tree_out->Branch( myVar,&var_out[i-1], Form("%s/F", myVar), basketsize);
}

Looping over the entries, the filling of the “scalarized” tree_out does not inspire confidence compared to the original “vectorized” one (viewed from TBrowser)

 Long64_t nentries = signal_in->GetEntries(); 
  for (Long64_t jentry=0; jentry<nentries;jentry++) {
   Long64_t ientry = signal_in->LoadTree(jentry);
   if (ientry < 0) break;
   signal_in->GetEntry(ientry);
 
   for (Int_t ivec = 0; ivec < 3; ivec++) {   //2 is the dimension of the vector
     for (Int_t ivar = 0; ivar < nvar; ivar++) {
       var_out[ivar] = (*varD)[ivec][ivar];
     }
     Tree_out->Fill();
   }
}
delete [] var_out;
delete [] varD ;

Using a vector of vector instead of arrays of vectors it is worse: the code crash with a segfault.
(just replacing like this:)

std::vector<std::vector<Double_t*> > * varD  =new<std::vector<std::vector<Double_t*> >;
....
signal_in->SetBranchAddress(myVar, &varD[i++]);

I’m not sure (even sure to be wrong …) that I am using properly the vectors & arrays components access, but more generally, anyway the problem seems to be more serious up to this point, can you see where I am wrong ?

Many thanks in advance for any help,
Cheers,
Arnaud

Hi,

Simply generate a dictionary for vector<vector > and use:

std::vector<std::vector<Double_t> > * varD =new<std::vector<std::vector<Double_t> >; ... outputTree->Branch("mystuff",&varD);.

To manipulate it you will probably need to move from MakeClass to MakeProxy.

Cheers,
Philippe.

Hi,
Many thanks for the quick reply, but I’m a bit confused (I’m beginner with root so sorry in advance for the naive questions…)
The goal of what I want to do starts from an initial tree containing N branches (as physical variables) of std::vectors (each of dimension d) per event (d can vary from an event to another one). I would like first to “scalarize” it ie: for each event, filling a new tree in which each vector component acts as an entry (with exactly the same branch structure).
I have succeded in it for a specified use with a given tree where all the necessary names can be hardcoded, but now, more generally, I would like to consider an unkown tree (so the ‘growing in dimension’ (e.g. defining a vector of vector) would intend here to include the flag of the running branch in addition of the rank of the vector component, this to store the information before filling the “scalarized” ntuple.
So to summarize, my problem is :

  • Looping on the branches of initial tree, how to set the correct adress of the j component of the i branch in a std:vectorstd::vector> (e.g. V)

  • then looping on the initial tree entries , how to link with the content of V[i][j] (aiming at filling the final tree)

Reading you’re prescription, I am confused by where and how taking the initial information (anyway I don’t know how to use properly the makeproxy in this case) (I’ve got also a strong constraint that is to write this within a method of some class from a standalone C++ code that does not allow to think the things in an interactive way…)

Thanks for any clarification or advice,
Cheers,
Arnaud

[quote]* Looping on the branches of initial tree, how to set the correct adress of the j component of the i branch in a std:vectorstd::vector> (e.g. V) [/quote]You can not set the addresses within the vector of vector. All you can do is to grab the whole vector of vector and iterator through that. So to read you would indeed need:std::vector<std::vector<Double_t> > * varD =new<std::vector<std::vector<Double_t> >; ... outputTree->Branch("mystuff",&varD);
Since your output and input have a different object structure, you would need to simply use a different variable and copy the information to this new variable. For example (humm … this is really just an example :slight_smile: I lost track of how many unrolling you need :slight_smile:) in pseudo code: inputTree->SetBranchAdress("myvectorOfVector",&vecOfvecPtr); double myvar; outputTree->Branch("unfolded","myvar/D",&myvar); // Or: // SimpleEvent *myEventPtr = new SimpleEvent; // outputTree->Branch("event",&myEventPtr); for each entry in inputTree; inputTree->GetEntry(entry); for each element of vecOfvec for each element of vector inside vecOfvec myvar = value of element of vector inside vector of vector; outputTree->Fill();

Cheers,
Philippe.

Hi,

You are also asking how to parse an arbitrary tree. This is actually quite complex if you can not put limit (i.e. conventions) to the type of TTree you support. For example of such general parsing see TBranchElement::SetAddress, TTreeFormula::DefinedVariable, TTree::MakeProxy, TTree::MakeClass, etc).

Cheers,
Philippe

Many thanks for your advice, (sorry also for my late answer), I have found a solution following your prescription, the main difficulty was to be careful with the rank of the various pointers to the vector of vector components.

Cheers,
Arnaud