Problem w/ vector<vector> after opening file w/ that type

Hi,

I am meeting a weird problem with loading vector of vector after opening a root file with that type variable in TTree object. In PyROOT I loaded the class generation and struct definition for vector of vector through a C++ macro “vecs.C”:

#include <vector>

#ifdef __CINT__
#pragma link C++ class vector<vector<float> >+;
#pragma link C++ class vector<vector<vector<float> > >+;
#endif

struct myStruct
{
  vector<float>                   *vF;
  vector<vector<float> >          *vvF;
  vector<vector<vector<float> > > *vvvF;

  vector<float>                   lvF;
  vector<vector<float> >          lvvF;
  vector<vector<vector<float> > > lvvvF;
};

In pyROOT I did the following script “test-vecs.py

from ROOT import (TFile,gROOT)

file = TFile("myVV_VVV.root")
tree = file.Get("qcd")

gROOT.ProcessLine(".L vecs.C+")
from ROOT import myStruct
m=myStruct()

# open root file after importing myStruct
# file = TFile("myVV_VVV.root")
# tree = file.Get("qcd")

fV  =m.vF
fVV =m.vvF
fVVV=m.vvvF

flV  =m.lvF
flVV =m.lvvF
flVVV=m.lvvvF

The above script crashed at “fVV =m.vvF”. If I moved root file opening after “m=myStruct()”, everything would work fine. Or fVV and lfVV (related to vector) would work fine if the root file does not have any TTree object containing with vector. Same for vector<vector>. The ROOT version with this crash is 5.28.00g. I also tried switch to ROOT later versions, says 5.34.00-rc1, which does not crash but leads to incomplete fVV, fVVV, lacking functions such as size and at, that is:

Any idea and solution?
Thanks.

–Shuwei

Shuwei,

w/o checking in detail (I don’t have your data file), but I’d think that the only thing that needs moving would be this line:gROOT.ProcessLine(".L vecs.C+")
It should be at the beginning, i.e. before opening the file. I think this is also true for C++. What would be even better, is if you generate a dictionary with a .rootmap file on the side. Then the auto-loading on TFile opening should work as expected (but again, haven’t tried).

Cheers,
Wim

Hi Wim,

I tried in C++. It worked fine whether a root file is opened prior to “.L vecs.C+” or after.

{
TFile *file = TFile::Open("myVV_VVV.root");
TTree* tree = file.Get("qcd");

gROOT->ProcessLine(".L vecs.C+");
myStruct m;

fV  =m.vF;
fVV =m.vvF;
fVVV=m.vvvF;

vector<float> flV  =m.lvF;
vector<vector<float> > flVV =m.lvvF;
vector<vector<vector<float> > > flVVV=m.lvvvF;
}

The test root file can be generated in the following way:

{
gROOT->ProcessLine(".L vecs2.C+");
myStruct m;

fV  =m.vF = new vector<float>;
fVV =m.vvF = new vector<vector<float> >;
fVVV=m.vvvF = new vector<vector<vector<float> > >;
vector<float> flV  =m.lvF;
vector<vector<float> > flVV =m.lvvF;
vector<vector<vector<float> > > flVVV=m.lvvvF;

TFile *newFile = TFile::Open("myVV_VVV.root","RECREATE");
TTree *newTree = new TTree("qcd","A TTree with VecOfVec VecOfVecOfVec variables");

newTree->Branch("p_vFloat",&fV);
newTree->Branch("p_vvFloat",&fVV);
newTree->Branch("p_vvvFloat",&fVVV);
newTree->Branch("vFloat",&flV);
newTree->Branch("vvFloat",&flVV);
newTree->Branch("vvvFloat",&flVVV);

flV.push_back(1);
flV.push_back(2);
flV.push_back(11);
flV.push_back(22);

flVV.push_back(flV);
fVV->push_back(flV);
flVVV.push_back(flVV);
flVVV.push_back(*fVV);

newTree->Fill();
newFile->Write();
newFile->Close();
}

The content of the ROOT macro “vecs.C+” (it would be more complicated in reality) and its struct name depend on the input root file, that is why I have to open the root file first. Any good solution for my case?

–Shuwei

Hi,

Tryfile->MakeProject("libforfile","*","RECREATE++");in the case you are reading a file.

Cheers,
Philippe.

Hi,

and if that doesn’t work, can you please provide a (sample) data file? I’ve tried various variations, but am unable to reproduce the problem. Thanks.

Cheers,
Wim

Hi Wim,

Attached please find a simple sample ROOT file with a TTree “qcd” containing vector and vector<vector >.

–Shuwei
myVV_VVV.root (6.61 KB)

Shuwei,

thanks; looks like a bug in TClass.

Even with the .C version and although the vectors work (if used after loading myStruct), asking the TClass for all public methods returns only zeroes:std::cout << TClass::GetClass("vector<vector<float> >")->GetListOfAllPublicMethods()->GetSize() << std::endl; std::cout << TClass::GetClass("vector<vector<float,allocator<float> >,allocator<vector<float,allocator<float> > > >")->GetListOfAllPublicMethods()->GetSize() << std::endl;if the file has been loaded before myStruct.

In the past, PyROOT used to delete STL classes with no methods, but Philippe told me not to. :slight_smile:

So Philippe, any ideas why there is this discrepancy?

The fix is very simple: if any empty STL classes are seen, then in PyROOT, all that is needed is this:ClassInfo_t* cl = gInterpreter->ClassInfo_Factory(name.c_str()); if (cl) gInterpreter->SetClassInfo(klass, kTRUE);and so I’ll check that in if there’s no better solution.

Thanks,
Wim

First try to:

gSystem->Exec("rm -f AutoDict*vector*vector*float*"); // just a precaution gInterpreter->GenerateDictionary("std::vector<std::vector<float> >", "vector"); gInterpreter->GenerateDictionary("std::vector<std::vector<std::vector<float> > >", "vector");
For “std::vector<std::vector >” see [url]Storing 2D vector [--> vector<vector<...> >] into a TTree
For “std::vector<std::vectorstd::string >” see [url]Problem in getting the vector < vector <string> > branch

Pepe,

at issue is that Shuwei does not know for certain that the vectors are needed: that’s only known after opening the file. Hence, the goal is to make both cases work: opening the file first, then loading the dict and v.v.

Cheers,
Wim

Well, Philippe proposed to use “MakeProject” but, in case of this file, it doesn’t seem to be working at all.
It seems to me that for both classes (v.v.f and v.v.v.f) one needs to “GenerateDictionary” manually.

Pepe,

Right, something funny is going on with TClass.

For now, I’ve checked the above snippet of code into v5-34-00-patches, as it appears to work in all cases. I’ll await a better solution. :slight_smile:

Cheers,
Wim

Hi,

Wim is correct. The problem was that in the case where the TClass for a STL collection (like vector<vector >) was accessed before the loading of the dictionary (i.e. opening the TFile before loading/creating the dictionary for vector<vector >).

This problem is solved by revision 45694 of the trunk and revision 45695 of the v5.34 patch branch.

Cheers,
Philippe.

Just to make it clear.
The fix, mentioned in the previous post, makes it possible to load dictionaries either before opening the file (the only option working before) or after opening the file (what was fixed).
However, one still needs to create and load appropriate dictionaries fully manually (and the “MakeProject” still doesn’t work in this case either).