Another 'who owns what' question

Hi everyone,

I’m lost with this. The below piece of code calls a function that creates and prints a histogram. After returning from the function call I would expect the histogram to have disappeared, like the legend and the canvas, but it’s still around. I don’t understand why and I don’t know how to get rid of the histogram. (I guess I could run over all histos in the current directory and destroy them, but that does not sound too cool.) It must have something to do with the legend, since commenting out the call to TLegend::AddEntry makes the histogram disappear, like the Canvas.

I’m pretty sure the histogram is owned by python, so this must mean the call to AddEntry has the side-effect of creating an extra reference to the histo? How do I figure out where this is and how do I get rid of it?

This happens both with ROOT v5.12/00 and python 2.4.3 on linux and with ROOT 5.14/00g and python 2.3.5 on OS X (Tiger).

Thanks,
Jeroen

#!/usr/bin/env python

import os

from ROOT import gROOT
from ROOT import TH1D
from ROOT import TCanvas
from ROOT import TLegend

def Func():

    hist_name = "hist_data"
    hist = TH1D(hist_name, hist_name, 1, 0., 1.)

    canvas = TCanvas("canvas")
    legend = TLegend(0.5, 0.9, 0.9, 1.0)

    legend.Clear()
    leg_entry = "blah"
    legend.AddEntry(hist, leg_entry, "l")

    canvas.Clear()
    hist.Draw()
    legend.Draw()

    # End

if __name__ == "__main__":

    gROOT.SetBatch(True)

    Func()
    if gROOT.FindObject("hist_data"):
        print "Histogram still exists... why, why, why?"
    else:
        print "Histogram is gone"
    if gROOT.FindObject("canvas"):
        print "Canvas still exists... why, why, why?"
    else:
        print "Canvas is gone"
    if gROOT.FindObject("TPave"):
        print "Legend still exists... why, why, why?"
    else:
        print "Legend is gone"

    # End of main.

Output:
Histogram still exists… why, why, why?
Canvas is gone
Legend is gone

Hi,

yes, the AddEntry() is the culprit: it takes the TH1D by non-const pointer, in which case pyroot gives up ownership in heuristic mode. If this is not the behavior that you want, you can use strict mode. Add at the top of your file:from ROOT import SetMemoryPolicy, kMemoryStrict SetMemoryPolicy( kMemoryStrict )
Alternatively, you can take ownership back after the AddEntry call, or even more explicit:legend.GetEntry().GetObject().Delete()
And yes, I know that not everyone is a fan of heuristic mode. :slight_smile: I’m open for better ideas.

Cheers,
Wim

Ach so. Now I understand what’s happening. Even better: now I know what to look for I see that’s it’s all documented as well :wink:

So this must be the ‘generalized converter’ case in PyROOT::CreateConverter(), right? (Sorry, I’m very nosy :slight_smile:.)

Thanks,
Jeroen

Jeroen,

right, but there is no “memory”: parameter passing follows the global setting of strict or heuristics as is current: if ( ! fKeepControl && Utility::gMemoryPolicy != Utility::kStrict )
Cheers,
Wim