Drawing in functions

Hi,
I’m trying to create a create 4 plots in four different pads. I’d like to call a function to do the drawing. However, Root’s memory management seems to delete the plot before it gets written out. I made a simplified version of my code

[code]#!/usr/bin/python

import sys, os, math
import ROOT
ROOT.gROOT.SetBatch(0)
ROOT.gStyle.SetPalette(1)
ROOT.gROOT.SetStyle(“Plain”)

def function_to_draw_some_important_plot(frame_num):
hist_name = “hist_%02d” % frame_num
hist = ROOT.TH1D(hist_name, “hist title”, 100, 0.0, 1.0)
myRand = ROOT.TRandom2()

for i in range(100000):
hist.Fill(myRand.Rndm())

hist.Draw()

#------------------------------------------------------------------

MAIN

#------------------------------------------------------------------
def main():

canvas = ROOT.TCanvas(“mi_can”,“tu_can”, 1000, 1000)
canvas.Draw()

#Draw 4 pads
pads = []
pad = ROOT.TPad(“plot_01”,“plot pad”, 0.0, 0.5, 0.5, 1.0)
pad.SetFillColor(ROOT.kRed - 2)
pad.Draw() # prevents seg. fault for some reason
pads.append( pad )

pad = ROOT.TPad(“plot_02”,“plot pad”, 0.51, 0.51, 1.0, 1.0)
pad.SetFillColor(ROOT.kBlue - 2)
pad.Draw()
pads.append( pad )

pad = ROOT.TPad(“plot_03”,“plot pad”, 0.0, 0.0, 0.5, 0.5)
pad.SetFillColor(ROOT.kGreen - 2)
pad.Draw()
pads.append( pad )

pad = ROOT.TPad(“plot_04”,“plot pad”, 0.51, 0.0, 1.0, 0.5)
pad.SetFillColor(ROOT.kYellow - 2)
pad.Draw()
pads.append( pad )

#Draw something in each pad
for iPad in range(len(pads)):
print 1, iPad, pads
pads[iPad].cd()
print 2, iPad, pads
function_to_draw_some_important_plot(iPad)
print 3, iPad, pads

print “\n”, pads
canvas.SaveAs(“a_test.gif”)
#Hey – Where did my histograms go?

Now, try drawing inline

pads[1].cd()
hist_name = “hist_%02d” % 5
hist = ROOT.TH1D(hist_name, “hist title”, 100, 0.0, 1.0)
myRand = ROOT.TRandom2()

for i in range(100000):
hist.Fill(myRand.Rndm())

hist.Draw()
canvas.SaveAs(“a_test_2.gif”)

#Wow, this time it works

if name == “main”:
print "Running as main . . ."
main()
[/code]

Thanks for any help.

Also, here’s a bonus question. Why does the following seg. fault?

pads = []
pads.append(ROOT.TPad("plot_01","plot pad", 0.0, 0.5, 0.5, 1.0))

This form is the work around:

pads = [] pad = ROOT.TPad("plot_04","plot pad", 0.51, 0.0, 1.0, 0.5) pad.SetFillColor(ROOT.kYellow - 2) pad.Draw() pads.append( pad )

Hi,

it’s not ROOT’s memory management, but simply Python’s ref-counting: objects created on the Python-side are owned by the interpreter (unless told otherwise) and hence local variables in you function go dodo.

Either release them from Python (ROOT will delete graphics objects that are handed to it when the parent graphics object goes away) by using e.g. ROOT.SetOwnership(hist, False) etc. or assign them to the pad that they belong to (and the pad to the canvas), so that the lifetimes are all the same (e.g. canvas.pads = pads and then append to that, etc.). It is also possible to tell a function never to return objects owned by Python, by setting its _creates member to False, but since that is then for all uses of that function, it’s not recommended.

Cheers,
Wim

Thanks.

I have a better understanding of the problems and assigning a reference to the TPad (though it mixes the Root/C++ and python paradigms) seems to keep the interpreter from deleting the histograms.