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

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.