Vector of vector in a tree - filling clone tree

Hello!

I am creating a tree with a vector of a vector

std::vector< std::vector<Float_t> > *truth;
_tree->Branch(“truth”,&truth);

At a later stage I want to loop over this tree, make cuts, and fill a clone of the tree if the event passes the cut

Opening the above created tree I do

vector< vector<Float_t> > truth;
_tree->SetBranchStatus("
",0);
_tree->SetBranchStatus(“truth”,1);
_tree->SetBranchAddress(“truth”,&truth);

_clonetree = (TTree*)_tree->CloneTree(0);

later on, if the event passes the cuts I do
_clonetree->Fill();

I get a seg fault when I try to fill the tree which comes from including this vector of vectors. This is the stack trace

*** Break *** segmentation violation
Using host libthread_db library “/lib/tls/libthread_db.so.1”.
Attaching to program: /proc/4943/exe, process 4943
[Thread debugging using libthread_db enabled]
[New Thread -1208887072 (LWP 4943)]
0x005d57a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x01c734b3 in __waitpid_nocancel () from /lib/tls/libc.so.6
#2 0x01c1c779 in do_system () from /lib/tls/libc.so.6
#3 0x005bb98d in system () from /lib/tls/libpthread.so.0
#4 0x008cccfd in TUnixSystem::Exec ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libCore.so
#5 0x008d3571 in TUnixSystem::StackTrace ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libCore.so
#6 0x008cf869 in TUnixSystem::DispatchSignals ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libCore.so
#7 0x008cf913 in SigHandler ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libCore.so
#8 0x008cea1e in sighandler ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libCore.so
#9
#10 0x00185c45 in TBufferFile::WriteFastArray ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#11 0x00195832 in TEmulatedCollectionProxy::WriteItems ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#12 0x0019602e in TEmulatedCollectionProxy::Streamer ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#13 0x0018af3d in TCollectionStreamer::Streamer ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#14 0x0018bab7 in TCollectionClassStreamer::operator() ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#15 0x00886229 in TClass::Streamer ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libCore.so
#16 0x00187a12 in TBufferFile::StreamObject ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#17 0x00195692 in TEmulatedCollectionProxy::WriteItems ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#18 0x0019602e in TEmulatedCollectionProxy::Streamer ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#19 0x0018af3d in TCollectionStreamer::Streamer ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#20 0x0018bab7 in TCollectionClassStreamer::operator() ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#21 0x00886229 in TClass::Streamer ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libCore.so
#22 0x0018624c in TBufferFile::WriteFastArray ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#23 0x00258a7e in TStreamerInfo::WriteBufferAux<char**> ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libRIO.so
#24 0x02c4481d in TBranchElement::FillLeaves ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libTree.so
#25 0x02c397be in TBranch::Fill ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libTree.so
#26 0x02c44478 in TBranchElement::Fill ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libTree.so
#27 0x02c8badb in TTree::Fill ()
from /d0usr/products/root/Linux-2-4/v5_22_00a-GCC_3_4_3-dz-rh7/lib/libTree.so

Any ideas what I am doing wrong?

Instead of

std::vector< std::vector<Float_t> > *truth; do

std::vector< std::vector<Float_t> > *truth=0;

Rene

Those declaration are in header files so I cannot do your suggestion exactly. I did however set truth = 0 before anything else is done.

I get this strange error now

Error in TTree::SetBranchAddress: The class requested (vector<vector >) for the branch “truth” refer to an stl collection and do not have a compiled CollectionProxy. Please generate the dictionary for this class (vector<vector >)

This is all in a c++ compiled executable.

I found this thread
root.cern.ch/phpBB2/viewtopic.php?t=4936

but when I put the mentioned lines in the header file of the class in which truth is declared, I still get the error.

[quote]when I put the mentioned lines in the header file of the class[/quote]Is the header file process either by ACLiC or by rootcint. If not then you are still not generating (nor loading) the needed dictionary.

Cheers,
Philippe.

So I am a bit lost…can you explain what is going on?

Hi,

As you may remember from reading the User’s Guide, in particular the Chapter 15 on Adding a Class, C++ does not provide enough information about the class ‘content’ for the I/O and interpreter to use them as is. To alleviate this lack, CINT (and thus ROOT) can create and load what we call ‘dictionaries’ ; once compiled, linked and loaded (as part of a shared library for example) it provides the interpreter and the I/O all the information you need. To create the dictionary you need to run rootcint:rootcint -f mydict.cxx -c myheader.h myLinkDef.h which will create a source file named mydict.cxx that you can compile and link as any of your other source file. The file myLinkDef.h is where you typically put the line#ifdef __MAKECINT__ #pragma link C++ class vector<vector<double> >+; #endif

These steps are simplified by ACLiC which will run rootcint, g++ and ld for you in order to create a shared library from just a simple source file (and its header). Hence the example you refer to where we recommend to create a single file named loader.C:// File loader.C #include <vector> #ifdef __MAKECINT__ #pragma link C++ class vector<vector<double> >+; #endif and ‘load’ it from the command line via:root [] .L loader.C+or from compiled code via gROOT->ProcessLine(".L loader.C+"); (from compiled code you could even use the underlying interface TSystem::CompileMacro).

Where and how did you use ‘#pragma’ line when it did not work for you?

Philippe.

Hi Phillippe,

I used the ‘#pragma’ line in the file which I compile to make the executable.

I have a class which has the tree as the private variable. I also tried putting the '#pramgma` line in that file. Both ( and the combination ) did not work.

I also followed you suggestion about generating a dictionary and linking it. My make file included

mydict.o: mydict.cxx mydict.h
$(CXX) -ggdb -c $(ROOTCFLAGS) $<

libmydict.so: mydict.o
g++ -shared -Wl,-soname,libmydict.so -o libmydict.so mydict.o

Then when compiling the final executable, I link the object created from the class which includes the tree, and link libmydict.so with -L./libmydict.so

I still get the same error and same crash

It would save time to you and us if
-you could identify your version
-you could could provide the shortest possible script reproducing your problem.

Rene

[quote]I used the ‘#pragma’ line in the file which I compile to make the executable[/quote]The question is wether or not you passed this file to rootcint when you generated the dictionary …

Hello,

I also want to write a vector<vector > to ntuple putting some cuts like you. Could you put your example how to write it?

Cheers.

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
P.S. In the first above example, simply replace all occurrences of “float” with “int” and you’ll get “std::vector<std::vector >”.