I would like to write my user class (created in C++ with dictionary generated) as TTree Branch in pyroot.
My user class is named ‘Source’ and inherits from another user class (inheriting from TNamed). The class is defined inside a user namespace (e.g. ‘MyLib’).
In C++ I am able to write the class to TTree (and reading it afterwards) using these sample code:
//Init
source= nullptr;
f= new TFile("out.root","RECREATE");
tree= new TTree("tree","tree");
tree->Branch("Source",&source);
//Create object and fill tree
s1= new MyLib::Source()
//set object parameters here
//...
source= s1;
tree->Fill()
//Write tree to file
f->cd()
tree->Write()
f->Close()
In python I am doing the following:
## Load modules
# - ROOT
import ROOT
from ROOT import gSystem, TFile, TTree, gROOT, AddressOf
# - My library
gSystem.Load('libMyLib')
from ROOT import MyLib
## Init
f= ROOT.TFile('test.root','RECREATE')
tree= ROOT.TTree('tree','tree')
source= MyLib.Source()
tree.Branch('Source',source)
## Create object and fill tree
s1= MyLib.Source()
//Set parameters here
s1.Id= 1
s1.Name= 's1'
//...
source= s1
source.Print() ## Here I print correctly the object attributes set before
tree.Fill()
## Write file
f.cd()
tree.Write()
f.Close()
The object is written to tree and accessible in file, but when I try to browse it (tree->Show(0)) the object parameters written are those initialized in the constructor (dummy values) and NOT those set at runtime (e.g. Id=1, Name=“s1”, etc).
For sure I am missing something trivial in python here (e.g. references).
For example copying s1 to source seems to work:
s1.Copy(source) # instead of source=s1
Could you in case help me to understand the problem and suggest the correct approach?
In Python all variables are just references. So, in your case the reference source points to the same object than reference s1 after the assigment source=s1 . The method Copy is needed to create a new instance (object).
As @mato mentioned, source and s1 are only references, so when you say source = s1 you update the source reference, but the branch still points to the old value of source. When you use s1.Copy(source), you copy the values from s1 into the object referred to by source, which is what you want. Have a look at the link below, towards the end there is some interesting exploration of Python objects.
thanks for all your answers. Yes, you’re right, after printing each object and inspecting their references, I realized the branch points to the “old” reference. I will copy the object(s) (actually in my code I have a collection of objects…) and have a look at the python object link you provided.