Problem in saving vector< vector <float> > into a TTree

Dear Rooters,

I have got a problem in saving (generated) detector signals into a TTree. The signals are copied to 2d-vectors of type std::vector< vector> (each channel == one 1d vector), but should be saved as 1d vectors of type std::vector.
The signal generator works fine, the signals are passed properly to the method, which will fill the vectors into the TTree, but their content is not saved. Saving std::vector directly into the Tree works fine (see the pGlTime vector of the attached code).
I attached a minimal (not) working example. Don’t be confused by creating the signals as local pointers and passing them to global variables. The code was extracted from a more complex QtRoot application.

Thanks in advance for your suggestions.

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

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

//global Variable definition
std::vector *pGlTime;
std::vector <vector > *pGlSignalVector;

TTree *pGlSignalTree;
TFile *pGlFile;

using namespace std;

void FillTTreeAcq()
{ //main method
//define signal characteristics
unsigned int NumEvents = 10000,
NumChannels = 1,
NumSamples = 1000,
BaseLine = 100,
Width = 300;
double Offset[] = {0.4,0.3,0.2,0.1};

//init global signal vectors
pGlTime         = new vector<float>();
pGlSignalVector = new vector <vector <float> >();

//define and init local signal vector
vector <float>              *pTime = new vector <float>();
vector <float>              *pSignal = new vector <float>();
vector <vector <float> >    *pSignalVector = new vector <vector <float> >();

//initializise the TFile and the TTree
init_TTree(NumChannels, NumSamples);
//fill the time vector
for (unsigned int i_sa=0; i_sa<NumSamples; i_sa++)

//define loop variables
unsigned int Event, i_ch;
//event loop  
for (Event=0; Event<NumEvents; Event++)
{   //loop over channels
    for (i_ch=0; i_ch<NumChannels; i_ch++)
    {   //generate signal and fill it to pSignal
        GenerateSignal( pSignal, NumSamples, BaseLine, Width, Offset[i_ch]);
    //record the signals
    RecordSignals(*pTime, *pSignalVector);

    //clear the signal vector

//write the TTree to TFile, close the TFile


double init_TTree(unsigned int NumChannels, unsigned int NumSamples)
{ //method to init the TTree
char tree_name[100] = “”;
char tree_description[100] = “”;
char branch_name[100] = “”;

//(re-)create  TFile
pGlFile = new TFile("Data.root", "RECREATE");

//set name and description of the TTree
sprintf(tree_name, "Signals");
sprintf(tree_description, "Tree containing signals from a generator");

//create the TTree
pGlSignalTree = new TTree(tree_name, tree_description);
    pGlSignalTree->Branch("time", &pGlTime, NumSamples, 0);
    for (int i_ch=0; i_ch<NumChannels; i_ch++)
    {   sprintf(branch_name, "channel%i",i_ch+1);
        pGlSignalTree->Branch(branch_name, &pGlSignalVector->at(i_ch), 

return 0;


void RecordSignals(vector pTime, vector< vector > pSignalVector)
{ //method to copy the produced signals into global variables and filling of
//the tree with them

//copy local to global vectors
pGlTime         = &pTime;
pGlSignalVector = &pSignalVector;


// for (int i_ch=0; i_ch<1; i_ch++)
// for (int i_sa=0; i_saat(i_ch).size(); i_sa++)
// cout << "Channel: " << i_ch << “\t”
// << pGlSignalVector->at(i_ch).at(i_sa) << endl;

//Fill the TTree

//clear the global vectors


void GenerateSignal(vector *pSignal, int Length, int BaseLine,
int Width, double Offset)
{ // method to create a logic signal with noise

// <------------------------Length--------------------------------->
// <—BaseLine---->
// Offset ________________ _____________________________________
// H | |
// e | |
// i | |
// g | |
// h | |
// t -------------
// <–Width–>

// double Height = gRandom->Uniform(0,-0.8);
double Height = gRandom->Gaus(-0.4, 0.1);
double noise;

//clear vector

for (int sample=0; sample<Length; sample++)
{   //Baseline
    if (sample<BaseLine)
    {   noise = gRandom->Gaus(Offset, fabs(0.01*Height));
    else if (sample<BaseLine+Width)
    {   noise = gRandom->Gaus(Offset+Height, fabs(0.01*Height));
    {   noise = gRandom->Gaus(Offset, fabs(0.01*Height));


FillTTreeAcq.cpp (5.89 KB)

In “RecordSignals” you overwrite “pGlSignalVector”.

This is true, but the intention is to copy the content of “pSignalVector” into the global counterpart “pGlSignalVector”. The current content of this global vector should be filled into the branches. So how this code can be modified to do this?

Do not use “pSignalVector” at all (BTW. assigning pointers is not copying the contents of objects they are pointing to).
Fill “*pGlSignalVector” and make sure that you do not reallocate it (you use “&pGlSignalVector->at(i_ch)” as branch addresses so these addresses must not change).