Fill vector<> from vector< vector< >> into TTree

Hi rooters,

I tried to save several vector from a vector< vector> into a root TTree. It is nessesary to save each vector into this tree seperately, to be able to use the features from TTreeViewer. Here is the smallest (not) working macro:

[code]//macro to save vector in TTree
//std. c includes
#include <stdlib.h>
#include <stdio.h>
#include

//root includes
#include “TTree.h”
#include “TFile.h”
#include “TBranch.h”

void FillTTree() {
//init vectors
std::vector *time_signal = new std::vector();
std::vector <vector > *waveform_vector = new std::vector <vector >();
//open file
f = new TFile(“Data.root”, “RECREATE”);
//define TTree
waveforms = new TTree(“waveforms”, “Tree containing Acqiris waveforms”);
waveforms->Branch(“time”,“vector”, &time_signal,1000,0);
waveforms->Branch(“channel1”,“vector”, &waveform_vector->at(0),1000,0);
waveforms->Branch(“channel2”,“vector”, &waveform_vector->at(1),1000,0);
waveforms->Branch(“channel3”,“vector”, &waveform_vector->at(2),1000,0);
waveforms->Branch(“channel4”,“vector”, &waveform_vector->at(3),1000,0);

//fill TTree
for (int events=0; events<1000; events++)
{ for (int i=0; i<4; i++)
{ waveform_vector->push_back(vector ());
for (int j=0; j<1000; j++)
{ if (i==0) time_signal->push_back(j);
waveform_vector->at(i).push_back((i+1)*j);
}
}
waveform1_vector = &waveform_vector->at(0);
waveform2_vector = &waveform_vector->at(1);
waveform3_vector = &waveform_vector->at(2);
waveform4_vector = &waveform_vector->at(3);
waveforms->Fill();
time_signal->clear();
waveform_vector->clear();
}
waveforms->Write();
f->Close();
}
[/code]
The root interpreter returns:
Error: Symbol #include is not defined in current scope FillTTree.cpp:29:
Error: Symbol exception is not defined in current scope FillTTree.cpp:29:
Syntax Error: #include FillTTree.cpp:29:
Error: Symbol G__exception is not defined in current scope FillTTree.cpp:29:
Error: type G__exception not defined FILE: FillTTree.cpp LINE:29
*** Interpreter error recovered ***

If one pass the pointer of a vector element of this vector< vector> to another 1d vector and saves this into the root Tree, everything is fine.
Is it possible to define a TTree in that way and pass such an Element to a Branch, like it is shown in the posted code??

Cheers
Toni

Hi Toni,

For this:waveforms->Branch("channel1","vector<float>", &waveform_vector->at(0),1000,0);the code must insure/guarantee that the waveform_vector is never resized. It should work properly if you do:waveforms_vector.resize(4); before creating the branches. It also means that you must remove the line:waveform_vector->push_back(vector<float> ());which does provoke a resizing of the waveform_vector (i.e. as the code is setup original the address passed to Branch are actually invalid/random).

Cheers,
Philippe.

1 Like

Hello Philippe,

thank you for your fast reply and the hints for my macro. I have removed the push_back(vector ()) line and now resizing the vector before I create the Branches. The resulting code is now:

[code]//macro to save vector in TTree
//std. c includes
#include <stdlib.h>
#include <stdio.h>
#include

//root includes
#include “TTree.h”
#include “TFile.h”
#include “TBranch.h”

void FillTTree() {
std::vector *time_signal = new std::vector();
std::vector <vector > *waveform_vector = new std::vector <vector >();

waveform_vector->resize(4);

f = new TFile("Data.root", "RECREATE");
waveforms = new TTree("waveforms", "Tree containing Acqiris waveforms");

waveforms->Branch("time","vector<float>", &time_signal,1000,0);
waveforms->Branch("channel1","vector<float>", &waveform_vector->at(0),1000,0);
waveforms->Branch("channel2","vector<float>", &waveform_vector->at(1),1000,0);
waveforms->Branch("channel3","vector<float>", &waveform_vector->at(2),1000,0);
waveforms->Branch("channel4","vector<float>", &waveform_vector->at(3),1000,0);

for (int events=0; events<1000; events++)
{   for (int i=0; i<4; i++)
    {   for (int j=0; j<1000; j++)
        {   if (i==0) time_signal->push_back(j);
            waveform_vector->at(i).push_back((i+1)*j);
        }
    }
    waveforms->Fill();
    time_signal->clear();
    waveform_vector->at(0).clear();
    waveform_vector->at(1).clear();
    waveform_vector->at(2).clear();
    waveform_vector->at(3).clear();
}
waveforms->Write();
f->Close();

}

[/code]

The return of the Interpreter is still:
Error: Symbol #include is not defined in current scope FillTTree.cpp:38:
Error: Symbol exception is not defined in current scope FillTTree.cpp:38:
Syntax Error: #include FillTTree.cpp:38:
Error: Symbol G__exception is not defined in current scope FillTTree.cpp:38:
Error: type G__exception not defined FILE:FillTTree.cpp LINE:38
*** Interpreter error recovered **

What’s wrong??

Thanks again.
Toni

Hi Toni,

I recommend you try:valgrind root.exe -b -l -q FillTree.C+ which will give us a better clue on what the problem is.

Cheers,
Philippe.

Modify your code:

// ... TFile *f = new TFile("Data.root", "RECREATE"); TTree *waveforms = new TTree("waveforms", "Tree containing Acqiris waveforms"); // ...
Then, try “root [0] .x FillTTree.cpp++”. It works for me.
Also “root [0] .x FillTTree.cpp” works.

Thank you both again.

I think this was a classical “version problem”. There is root 5.26.00 installed here and now I tried it on 5.28.00 and it works! There was a change in 5.28.00 I think, which adresses the TTree, right? I think, I read about it in another post.

The quick support in this forum is very great. Thank you.

Cheers
Toni

Hi Toni,

Very possible. Please note that in newer version of ROOT, you can use:waveforms->Branch("channel1",&waveform_vector->at(0),1000,0);which automatically detect the data type.

Cheers,
Philippe.