Writing 2D vectors to root files

Hi Rooters,
I am trying to save 2D vectors to root files for later analysis.

I have done this successfully in the past with 2D arrays doing the following:

float test[100][100];
selection->Branch(“test”,&test,“test[100][100]/F”);

I am trying to do use something like this for 2D vectors:

vector <vector > test;
selection->Branch(“test”, &test, “vector < vector >”);

Later on in the code, I fill vector test using .push_back

This code does compile and run; however, examination of the branch ‘test’ in TBrowser gives me a distribution that is not what I expect.

My questions are the following:

  1. Did I use the correct procedure to save my 2D vector to a root file
    and
  2. How can I read the branch ‘test’ and assign it to a vector object in my code.

With regards to question 2, previously, I have done the following with 2D arrays:

float test[100][100];
chain->SetBranchAddress(“test”,&test);

What is the analogous code to use for 2D vectors?

Would something like this work:

vector < vector > test;
chain->SetBranchAddress(“test”,&test);

Instead of

vector <vector <float> > test; selection->Branch("test", &test, "vector < vector <float> >"); do

vector < vector<float> > test; selection->Branch("test",&test);
as shown in this short example that you can run with ACLIC

//file vv.C #include "TTree.h" #include <vector> #ifdef __MAKECINT__ #pragma link C++ class std::vector < std::vector<float> >+; #endif void vv() { TTree *T = new TTree("T","test"); vector < vector<float> > test; T->Branch("test",&test); T->Print(); }
and then in ROOT do

root > .x vv.C+
If you do not run with ACLIC, you must create a dictionary for your class.

Rene

Hi Rene,
Thanks for your reply. I tried playing with the code but for some reason, I still can’t quite get it to work. I wrote out a full example illustrating what I am trying to do.

#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <fstream>
#include <iostream>
#include <vector>

#include "TFile.h"
#include "TTree.h" 
#ifdef __MAKECINT__
#pragma link C++ class std::vector < std::vector<int> >+;   
#endif 

void save()
{
  cout<<"This is a test..."<<endl;
  TFile rootfile("test.root","RECREATE");
  TTree *PostSel =new TTree("PostSel","Data for calibration");

  vector <vector <int> > test;
test.push_back ( vector<int>() );
  PostSel->Branch("test",&test);  //THIS IS LINE 21
 
//some code to fill sample file
  for(int event=0; event<10; event++)
    {
      for(int ii=0;ii<10;ii++)
	{
	  test[0].push_back(ii+1);   //THIS IS LINE 27
	}
      PostSel->Fill();
    }
  rootfile.Write();
  rootfile.Close();
}

When I run .x save.C+, I get the following errors:

/home/andy/model/test/./save.C:21: error: invalid conversion from ‘std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >*’ to ‘Int_t’                                                   
/home/andy/model/test/./save.C:21: error:   initializing argument 2 of ‘virtual Int_t TTree::Branch(const char*, Int_t, Int_t)’                                 
/home/andy/model/test/./save.C:27: error: no matching function for call to ‘std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::push_back(int)’ 

The relevant line numbers are labelled in my code.

Hi,

The syntax ‘tree->Branch(name,object);’ is only supported in ROOT v5.20 and above. Which version are you using?

Philippe.

Hi Phillippe, that was the problem. After upgrading from 5.18 to 5.26, it now seems to be working :smiley:

I now seem to be having a problem with reading back the vector I had previously stored in a ROOT file.

Here is a sample code I have written to try to accomplish this. It compiles correctly but seg-faults when I go to execute it.

#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <fstream>
#include <iostream>
#include <vector>

#include "TFile.h"
#include "TTree.h" 
#include "TChain.h"
#ifdef __MAKECINT__
#pragma link C++ class std::vector < std::vector<int> >+;   
#endif 

void read()
{
  TChain *chain = new TChain("PostSel");
  chain->Add("test.root");

  vector < vector <int> > test;
  chain->SetBranchAddress("test",&test);

  Int_t nevents = (Int_t)chain->GetEntries();
  Int_t nbytes = 0;
  cout << " Total events read from the chain: "<<nevents<<endl;

  for(int istock=0;istock<nevents;istock++)
    {
      nbytes += chain->GetEntry(istock);
      cout<<test.size()<<endl;
      cout<<istock+1<<":"<<test[0][4]<<":"<<test[0][5]<<endl;
    }
}

Hi,

SetBranchAddress has not yet been upgraded to support the object syntax, so you still need to use:vector < vector <int> > *test = 0; chain->SetBranchAddress("test",&test);
Cheers,
Philippe.

Hi Phillippe,
I made that adjustment to my code but now I am getting an error which prevents it from compiling. When I run code with the following line:

test.size()

I get the following error:

/home/andy/model/test/./read.C:30: error: request for member ‘size’ in ‘test’, which is of non-class type ‘std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >*’ 

It appears like I am unable to treat the object test as a standard vector. How can I work around this?

Hi,

Since ‘test’ is now a pointer to a vector, C++ requires that you use the following syntax to access the member functions:test->size();
or code.size()[/code]

Cheers,
Philippe.

Hi Philippe, that fixed my problem, I now understand what is going on.

Hello
I am using ROOT 5.22 and I compile my program instead of loading it with .x or similar things.

I have this in my code

vector<vector<int> > test;
t->Branch("test", &test);

that gives me
"Error in TTree::Branch: The pointer specified for test is not of a class or type known to ROOT"

Notice that I can use vector types, but I had to include

	gROOT->ProcessLine("#include <vector>");

in the code. I do not know how to generalize this fix to work for the vector<vector > type. Note as well that I have some “dictionary line”

#ifdef __MAKECINT__
#pragma link C++ class std::vector<int>+;
#pragma link C++ class std::vector<float>+;
#pragma link C++ class std::vector < std::vector<float> >+;
#pragma link C++ class std::vector<int>+;
#pragma link C++ class std::vector < std::vector<int> >+;
#pragma link C++ class std::string+;
#pragma link C++ class std::vector<string>+;
#endif

whose presence does not seem to affect the functionality of neither vector nor vector<vector >
Can you help me?
Thanks a lot
Roberto

Hi,

The line:#pragma link C++ class std::vector < std::vector<int> >+; is the one you needed. Did you make sure that this line is seen by either rootcint (and then you compiled, linked and loaded the result) or by ACLiC?

Cheers,
Philippe.

I think is better to keep discussing in
root.cern.ch/phpBB2/viewtopic.php?p=41761#41761