Std::vector TTree branches emptying when written

I’m having trouble opening and rewriting a tree with std::vector branches. It seems that whenever I call tree->Write(), the vector branches lose all original information. Here is a simplfiied example of the code I am using. The header file is generated from MakeClass on the original tree, and has vector branches like:

vector<float> *jetPt;
TBranch *b_jetPt; //!

In Init of the header file it does the following:
// Set object pointer
jetPt = 0;
fChain->SetBranchAddress("jetPt", &jetPt, &b_jetPt);

In the actual function, I just get the tree, get the number of entries, and then write it.

TTree* fChain = (TTree*)F.Get(treename.c_str());
if( fChain !=NULL ) {
Long64_t N = fChain->GetEntries();}
fChain->Write();

Before this action, I can draw the jetPt variable and jetPt[0] with no problems. After the action, while the branch still has the correct number of entries when I print the tree, when I draw this variable the histogram comes up Empty.

When I tried researching this behavior, I came across the root-forum ticket here: Leak when reading std::vector. I then tried to add the following 2 lines before I write the tree:

tree->ResetBranchAddresses();
delete v;

But this doesn’t fix the jetPt branch saving. It seems that this is a strange memory-related abnormality of having a pointer to the std::vector, but any advice would be appreciated! I’m using Root version 6.10.04.

Hi,

would in this case a higher level interface be easier to use? For example, TDataFrame snapshot capabilities could be leveraged.
(irrespective of that, I suggest to move to ROOT 6.12.06)

Cheers,
D

You are setting the pointer to null here, and passing the address of the pointer to SetBranchAddress(), rather than the pointer itself. One of those two things are causing the problem you see. Try using a normal std::vector and passing a reference to it, or passing the pointer instead of the address of the pointer.

Hi @amadio,

Thanks for taking a look! However I can’t find a way to get either of these solutions to work. If I try the first one (below), I can get a jetPt that draws like the original histogram if I only write the tree. But if I try to call GetEntry on this tree, it crashes. (I imagine that if I call a MakeClass on the tree and it gives me a pointer to the vector by default, it will not work to change this manually to a vector?)

vector<float> jetPt;
TBranch *b_jetPt; //!
//jetPt = 0; comment this since it's not needed anymore
fChain->SetBranchAddress("jetPt", &jetPt, &b_jetPt);

As for the second option, you suggest to do something like this? I’m not sure how to get your suggestion of passing the pointer instead of the address to work with SetBranchAddress.
vector<float> *jetPt;
jetPt = 0;
fChain->SetBranchAddress("jetPt", *jetPt, &b_jetPt);

Thanks!
Julia

Hi Julia, maybe you could follow the tutorial for this at https://root.cern.ch/doc/master/hvector_8C.html.
In there it shows how to store and read std::vectors. Cheers,

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