TTree::SetBranchAddress() for a TGraph array branch

I have a TTree “waveformGraphTree” with a branches “cohGraphs[2]” and “deconvGraphs[2]” made with the lines

	TGraph cohGraphs[2], deconvGraphs[2];
	waveformGraphTree.Branch("cohGraphs[2]", "TGraph", & cohGraphs);
	waveformGraphTree.Branch("deconvGraphs[2]", "TGraph", & deconvGraphs);

Later on, I would like to reference the TGraphs from these branches in another function with pointer to the TTree as input, and so I try

	TGraph cohGraphs[2], deconvGraphs[2];
	waveformGraphTree -> SetBranchAddress("cohGraphs[2]", & cohGraphs);
	waveformGraphTree -> SetBranchAddress("deconvGraphs[2]", & deconvGraphs);

However, I then receive the following output:

Error in <TTree::SetBranchAddress>: Unable to determine the type given for the address for "cohGraphs[2]". This is probably due to a missing dictionary, the original data class for this branch is TGraph.
Error in <TTree::SetBranchAddress>: Unable to determine the type given for the address for "deconvGraphs[2]". This is probably due to a missing dictionary, the original data class for this branch is TGraph.

TTree::SetBranchAddress() is overloaded, am I supposed to have another input variable? I have also tried #include "TGraph.h" beforehand.


_ROOT Version:6.12/06
Platform: linuxx8664
Compiler: gcc


What do you get from waveformGraphTree->Print();

	TGraph cohGraphs[2], deconvGraphs[2];
	waveformGraphTree.Branch("cohGraphs[2]", "TGraph", & cohGraphs);

This will save only one of the 2 TGraph object. Use

	std::vector<TGraph> cohGraphs, deconvGraphs;
	waveformGraphTree.Branch("cohGraphs[2]", "TGraph", & cohGraphs);

SetBranchAddress expects the address of a pointer or the address a single object.

Hi Philippe,

Thanks for the informative response. I tried taking it a step further and tried

vector<TGraph> cohGraphs(2), deconvGraphs(2);
waveformGraphsTree.Branch("cohGraphs[2]", "TGraph", & cohGraphs);
waveformGraphsTree.Branch("deconvGraphs[2]", "TGraph", & deconvGraphs);

When I call cohGraphs, I get reference address inside of the vector, in contrast to when I try cohGraphs[2], where I get an empty vector of size 2.

However, with the above lines I get

Error in <TTree::Branch>: The class requested (TGraph) for "cohGraphs[2]" is different from the type of the object passed (vector<TGraph>)
Warning in <TTree::Bronch>: Using split mode on a class: TGraph with a custom Streamer
Error in <TTree::Branch>: The class requested (TGraph) for "deconvGraphs[2]" is different from the type of the object passed (vector<TGraph>)
Warning in <TTree::Bronch>: Using split mode on a class: TGraph with a custom Streamer

Even if I know what the size of the vectors should be beforehand, should I not assign sizes beforehand and a vector’s “push_back()” to add in the graphs later?

Hi!

Thank you for the response. I tried implementing Philippes’ suggestion below, so that will likely change what waveformGraphTree->Print(); returns. What it now returns is

******************************************************************************
*Tree    :waveformGraphTree: TTree containing TGraphs of initial waveforms.         *
*Entries :      189 : Total =        19026755 bytes  File  Size =   19019994 *
*        :          : Tree compression factor =   1.00                       *
******************************************************************************
*Br    0 :run       : run/I                                                  *
*Entries :      189 : Total  Size=       1316 bytes  File Size  =        839 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    1 :eventNumber : eventNumber/i                                        *
*Entries :      189 : Total  Size=       1356 bytes  File Size  =        847 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    2 :cohGraphs[2] : vector<TGraph>                                      *
*Entries :      189 : Total  Size=    9513996 bytes  File Size  =    9509882 *
*Baskets :      189 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    3 :deconvGraphs[2] : vector<TGraph>                                   *
*Entries :      189 : Total  Size=    9509503 bytes  File Size  =    9505377 *
*Baskets :      189 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*

Even if I know what the size of the vectors should be beforehand, should I not assign sizes beforehand and a vector’s “push_back()” to add in the graphs later?

Both will work.

Error in TTree::Branch: The class requested (TGraph) for “cohGraphs[2]” is different from the type of the object passed (vector)

The message is correct. You can just skip specifying the type.

waveformGraphsTree.Branch("cohGraphs[2]", & cohGraphs);

Cheers,
Philippe.

Thanks for the help, Philippe.

I looked into your comment

SetBranchAddress expects the address of a pointer or the address a single object.
and found a response you provided earlier
Vector in Branch - #5 by pcanal

So returning to the initial question, what I have tried now that the TGraphs are being properly stored is

	vector<TGraph> * cohGraphs, * deconvGraphs;
	waveformGraphTree -> SetBranchAddress("cohGraphs[2]", cohGraphs);
	waveformGraphTree -> SetBranchAddress("deconvGraphs[2]", deconvGraphs);

Using TTree::SetBranchAddress() as above doesn’t throw any errors at this point, but now a function which I call later which referenced & cohGraphs[0] when I had

vector<TGraph> cohGraphs(2);

Now returns

error: cannot initialize a parameter of type 'const TGraph *' with an rvalue of type
      'vector<TGraph> *'

Things appear to work if I do

vector<TGraph> * cohGraphs[2], * deconvGraphs[2];

and then provide the function with the argument cohGraphs[0] -> data(), but is that the correct thing to do? What if instead I did

vector<TGraph> * cohGraphs, * deconvGraphs;

and then passed as argument cohGraphs[0].data()? Both of these seem to work, but are they effectively doing the same thing?

Best,
John