Error in <TTree::Branch> - Vector issue

Dear rooters

First of all I would like to thank you in advance for any help. I am developing a program in C++/QT5 in which I have linked the ROOT libraries. I am using root 5.34 for the moment. I am facing the following very trivial problem but I cannot find a way to solve it.

I am creating a TTree which I want to fill, for example :

chIdBranch = vmm2->Branch(“channel”,&chIdVariable);

but once I am running the code I get:

Error in TTree::Branch: The pointer specified for channel is not of a class or type known to ROOT

I have read about generating dictionary but whatever I have done I didn’t succeed and I am out of ideas…

Any help is highly appreciated !

Thanks a lot,
George

Hi George,

I think we really need a dictionary here.
Could you post the header file and implementation of the class of which chIdVariable is an instance? That is all one needs to create a dictionary.

Cheers,
Danilo

Dear Danilo

Thanks a lot for the reply. I attach the file here. The mainwindow.h is the header file in which I am declaring the vectors (line 82) and the mainwindow.cpp the class implementation where I am using them to declare the branches (line 2282). Sorry I am not a good programmer as you will see and that’s why I need some help ! Thank you very very much in advance !

Regards,
George
mainwindow.h (7.63 KB)
mainwindow.cpp (137 KB)

Hi George,

as far as I can see you need only to write std::vector instances.
ROOT already provides the dictionaries to perform this operation, so no need to generate any new dictionary or doing anything special. I/O of stl collections in trees is seamlessly supported.
See for example this tutorial:
root.cern.ch/root/html/tutorial … ion.C.html

Danilo

Hi Danilo

Thanks for the help I appreciate it. I think I’ve seen the example but I couldn’t really manage to succeed. For example root can generate by gIntepreter->GenerateDictionary command a dictionary for vector of vectors but I have not succeed to use them… I am still getting the same errors…

Thanks
George

Let’s separate the problems:

  1. If we restrict our focus to the files you posted, there is no vector of vectors branch in your tree, just vector. This must work with ROOT w/o generating dictionaries. If it does not in your case, one fruitful strategy could be to slim down the usecase to a bunch of lines which reproduce the problem.
  2. if you need to persist a vector of vectors, you need to create a dictionary: root does not ship it by default. In this case, what is the issue with the dictionary generation?

Hi Danilo

Thanks for the reply.

I use vector<vector > in the code and that’s where I run into problems. With these vector of vectors when I use them in branches I get the error that ROOT
Error in TTree::Branch: The pointer specified for channel is not of a class or type known to ROOT
although it’s a vector of vectors of int. That’s what I don’t understand either.

I had the same issue with just vectors which I solve by doing :
evSizeBranch = vmm2->Branch(“eventSize”,“std::vector”,&evSizeVariable);
instead of
evSizeBranch = vmm2->Branch(“eventSize”,&evSizeVariable);

If I do the same with vector of vectors of int I run into problems… The thing is that this is a huge code in QT which I don’t know how to make it small and show you a small reproducible problem.

What is more surprising is that this code was working in root 5.28 with no issues…

Thank you very much for the effort.

Regards,
George

For “std::vector<std::vector >” see [url=https://root-forum.cern.ch/t/storing-2d-vector-vector-vector-into-a-ttree/14331/2
For “std::vector<std::vectorstd::string >” see [url=https://root-forum.cern.ch/t/problem-in-getting-the-vector-vector-string-branch/14608/4

Hi George,

I missed the type of the branch as the code was spread between a long-ish header and implementation :frowning:
So, here you can find the steps to create a dictionary, compile it as a shared lib, load it into a program.
a.h

#include <vector>
namespace dummy_a{ // dummy instantiations
  std::vector<std::vector<int> > a1;
}

LinkDef.h

#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class vector<vector<int> >+;
#endif

Commands to create the shared library

rootcint -f aDict.cxx  -c  a.h LinkDef.h
g++ -o libMylib.so aDict.cxx `root-config --cflags --libs` -shared -fPIC

test macro

{
TFile ofile("ofile.root","RECREATE");
gSystem->Load("libMylib.so");
vector<vector<int> > v;
vector<int> a;
a.push_back(1);
a.push_back(2);
v.push_back(a);
ofile.WriteObjectAny(&v, "std::vector<std::vector<int> >", "v");
}

If you are interested in the newest ROOT version, version 6, I can post the same recipe: it is much simpler.

Cheers,
Danilo

Dear Danilo

I owe you a beer for sure !! Thank you very much, I think I managed to implement this correctly, at least I get no errors once I initialise the branches now. Having it for ROOT 6 would be nice because soon I’ll be into it.

Many many thanks for the valuable help.

Best Regards,
George

Hi George,

for ROOT6, you can just use the same commands: the two versions are compatible.
Alternatively, you could formulate the selection as follows
myselection.xml

<rootdict>
  <class name="vector<vector<int>>" />
</rootdict>

commands

genreflex a.h -s myselection.xml --rootmap myRootmap.rootmap
g++ -o libMylib.so a_rflx.cxx `root-config --cflags` -shared -fPIC

You noticed the generation of the rootmap. This file allows root to automatically load the library and can be generated together with the dictionaries in version 6. Concretely, you don’t have to bother loading the library yourself, i.e. you can remove “gSystem->Load(“libMylib.so”);”.

Cheers,
Danilo

Thanks Danilo ! I’ll try this soon.

Best Regards
George