Who owns clones in PyROOT?

Dear experts,

When I want a new, say, TLorentzVector equal to one I already have, in Python I have to explicitly copy/clone the original. But when I do this

from ROOT import TLorentzVector
ori = TLorentzVector()
new = ori.Clone()

where does the clone live? Normally, in C++, I would have to take care of it and delete it when done. Who owns the clone here (and if I need to, how do I delete it?) Will it be deleted (collected) when ‘new’ goes out of scope, or more precisely, when the ref count to the clone becomes zero?

Thanks for your help,
Jeroen

P.S. Where/how would I go and find this in the code? Somewhere in TPyROOTApplication?

Jeroen,

there is no information available on a returned pointer as to who owns the memory (triggering on the name “Clone” in heuristic mode is still on my TODO list). Therefore, in order to have the clone deleted, you’ll need to do:import ROOT ROOT.SetOwnership( new, True )

This is one of those unfortunate edges where you can’t forget that the code underneath is C++ and can therefore leak.

HTH,
Wim

Hi Wim,

Thanks for the info. Is this still the right way to do? I mean, if I want to create a smeared version of a given TLorentzVector, should I be taking this route, or are there other/better approaches.

Cheers,
Jeroen

Jeroen,

[quote]Is this still the right way to do?[/quote] Good question; I should’ve spent some cycles on that.

First: for TLorentzVector? No: the raison d’etre of Clone(), is to allow the return of a copy of the actual type. You’re not going to derive from TLorentzVector in what I think I understand from your posting, so this would be the way:new = TLorentzVector( ori ) (that is, simply use the copy constructor so that ownership is taken by python).

But now that I think of it, in general if you have all dictionaries in the inheritance tree (true for all ROOT classes), the python type that you have for any object is the actual type, so there’s no point to use Clone() unless the copy constructor is access protected (in C++). That is, you can do:new = ori.__class__( ori )in general cases, thereby emulating the Clone() behavior while keeping ownership rules strictly to python reference counting.

Cheers,
Wim