Open vepadulano opened 9 months ago
Hi @pcanal @vepadulano
I was not able to reproduce the original error. The following piece of code does the following:
If I understand correctly the OP and a later comment by @pcanal in the ROOT forum, the call tree->SetMakeClass(1);
would be needed for the second case, however it works without it.
#include "TFile.h"
#include "TTree.h"
#include "TBranch.h"
#include <iostream>
class myclass
{
public:
int x = {0};
int y = {0};
};
void printTree_splitclass(const char *path) {
std::cout << __FUNCTION__ << '\t';
printf("%s:\n", path);
std::unique_ptr<TFile> file(TFile::Open(path));
auto *tree = file->Get<TTree>("tree");
int x,y;
tree->SetBranchAddress( "mybranch.x", &x );
tree->SetBranchAddress( "mybranch.y", &y );
//tree->SetMakeClass(1);
for( int i =0; i< tree->GetEntries(); ++i)
{
tree->GetEntry(i);
std::cout << '\t' << x << std::endl;
}
}
void printTree_fullclass(const char *path) {
std::cout << __FUNCTION__ << '\t';
printf("%s:\n", path);
std::unique_ptr<TFile> file(TFile::Open(path));
auto *tree = file->Get<TTree>("tree");
myclass * object4branch = new myclass();
tree->SetBranchAddress( "mybranch", &object4branch );
//tree->SetMakeClass(1);
for( int i =0; i< tree->GetEntries(); ++i)
{
tree->GetEntry(i);
std::cout << '\t' << object4branch->x << std::endl;
}
}
void ROOT_1853() {
{
std::unique_ptr<TFile> file(TFile::Open("b.root", "RECREATE"));
TTree *tree = new TTree("tree", "title");
myclass object4branch;
tree->Branch("mybranch", &object4branch);
for( int i = 0; i< 10; ++i)
{
object4branch.x = i;
object4branch.y = -i;
tree->Fill();
}
tree->Write();
}
printTree_fullclass("b.root");
printTree_splitclass("b.root");
}
Now I am not sure if the call of SetMakeClass
is automatically done, and therefore this function became internal, or if it is still worth to be documented.
I managed a reproducer:
First run this tutorial. https://root.cern/doc/master/tree4_8C.html
Then run:
root -l 'openTree.C(0)' -b -q
Processing openTree.C(0)...
7.31217e-322ºC
root -l 'openTree.C(1)' -b -q
Processing openTree.C(1)...
20.2826ºC
File openTree.C:
#include <iostream>
#include "TFile.h"
#include "TTree.h"
void openTree(bool setMakeClass = false) {
auto f = TFile::Open("tree4.root");
TTree *t4 = (TTree*)f->Get("t4");
t4->SetMakeClass(setMakeClass);
Double32_t temp;
TBranch *br = t4->GetBranch("fTemperature");
br->SetAddress(&temp);
br->GetEntry(0);
std::cout << temp << "ºC" << std::endl;
}
I managed a reproducer:
First run this tutorial. https://root.cern/doc/master/tree4_8C.html
Then run:
root -l 'openTree.C(0)' -b -q Processing openTree.C(0)... 7.31217e-322ºC root -l 'openTree.C(1)' -b -q Processing openTree.C(1)... 20.2826ºC
File openTree.C:
#include <iostream> #include "TFile.h" #include "TTree.h" void openTree(bool setMakeClass = false) { auto f = TFile::Open("tree4.root"); TTree *t4 = (TTree*)f->Get("t4"); t4->SetMakeClass(setMakeClass); Double32_t temp; TBranch *br = t4->GetBranch("fTemperature"); br->SetAddress(&temp); br->GetEntry(0); std::cout << temp << "ºC" << std::endl; }
Hi,
I suspect about an issue in the tree4.C file that is leading to this subsequent error: when writing the branches, each branch name should end with a dot to avoid degeneracy (objects of the same class are used for 2 different branches).
Please see this tutorial and particularly this comment by @pcanal during the review: https://github.com/root-project/root/pull/13205#discussion_r1265655686
Can you try generating the ROOT files with that modification and checking if the error persist?
@vepadulano would it be worth to add P. Canal comment about the dot at the end of the branch name into the TTree web documentation?
Best, Alvaro
I suspect about an issue in the tree4.C file that is leading to this subsequent error: when writing the branches, each branch name should end with a dot to avoid degeneracy (objects of the same class are used for 2 different branches).
You mean setting the branch name as "event_split." and "event_not_split." ? But are there any subelements with the same name there?
root -l 'openTree.C(0)' -b -q
Processing openTree.C(0)...
7.31217e-322ºC
root -l 'openTree.C(1)' -b -q
Processing openTree.C(1)...
20.2826ºC
This is the expected result. TBranch::SetAddress
is a lower level interface and has less ability to check for incorrect setup.
Without SetMakeClass
, if the branch is within an object (i.e. the case here), the input of SetAddress
is expected to be the start of the object (and thus the offset of the data member is added to the provided address). The explicit purpose of SetMakeClass
is to disable this addition of the offset.
Note that TTree::SetBranchAddress
will detect this case and automatically call SetMakeClass
for the branch:
t4->SetBranchAddress("fTemperature", &temp);
Explain what you would like to see improved and how.
From https://its.cern.ch/jira/browse/ROOT-5159
It recently took me many many hours to figure out that my code could not read out a branch because TTree::SetMakeClass() was not set. As far as I can tell this is neither explained in the ROOT manual, nor the TTree documentation page. I found a old RootTalk message (http://root.cern.ch/root/roottalk/roottalk03/1853.html) regarding it, but only post mortem because one has to search for SetMakeClass, and at least this one had no clue that SetMakeClass was the problem to begin with.
Some explanation and warning about this feature in the TTree documentation would be very much appreciated.
Sue Ann Koay sakoay@cern.ch
ROOT version
Any
Installation method
Any
Operating system
Any
Additional context
No response