PyROOT Troubles writing user class to TTree

Dear all,

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:

source= nullptr;
f= new TFile("out.root","RECREATE");
tree= new TTree("tree","tree");

//Create object and fill tree
s1= new MyLib::Source()
//set object parameters here
source= s1;


//Write tree to file

In python I am doing the following:

## Load modules
# - ROOT
import ROOT
from ROOT import gSystem, TFile, TTree, gROOT, AddressOf

# - My library
from ROOT import MyLib

## Init
f= ROOT.TFile('test.root','RECREATE')
tree= ROOT.TTree('tree','tree')
source= MyLib.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

## Write file

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?

Thank you very much for your help,


Somebody who knows Python better than me (e.g. @amadio or @mato) could maybe tell you if you have to copy it or not…

this worked for me:

import ROOT

ROOT.gROOT.ProcessLine("struct Event { Int_t ID; Double_t Data; };")

f = ROOT.TFile.Open("my.root", "RECREATE")
t = ROOT.TTree("t","my tree")

evt = ROOT.Event()
t.Branch("evt", evt)

for i in range(100):
    evt.ID = i+1
    evt.Data = float(100 * (i+1))


and then:

$> root ./my.root
root [0] 
Attaching file ./my.root as _file0...
Warning in <TClass::Init>: no dictionary for class Event is available
(TFile *) 0x55ada42f40c0
root [1] auto t = (TTree*)_file0->Get("t")
(TTree *) 0x55ada403ab40
root [2] t->Scan()
*    Row   *    evt.ID *  evt.Data *
*        0 *         1 *       100 *
*        1 *         2 *       200 *
*        2 *         3 *       300 *
*        3 *         4 *       400 *
*        4 *         5 *       500 *
*        5 *         6 *       600 *
*        6 *         7 *       700 *
*        7 *         8 *       800 *
*        8 *         9 *       900 *
*        9 *        10 *      1000 *
*       10 *        11 *      1100 *


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.

Dear all,

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.



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