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”:
#pragma link C++ class vector<vector<float> >+;
#pragma link C++ class vector<vector<vector<float> > >+;
vector<vector<float> > *vvF;
vector<vector<vector<float> > > *vvvF;
vector<vector<float> > lvvF;
vector<vector<vector<float> > > lvvvF;
from ROOT import (TFile,gROOT)
file = TFile("myVV_VVV.root")
tree = file.Get("qcd")
from ROOT import myStruct
# open root file after importing myStruct
# file = TFile("myVV_VVV.root")
# tree = file.Get("qcd")
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:
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).
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?
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.
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.
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.
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.
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.
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).