Returning TH1F from function

I’m just getting used to using PyROOT and have found that it simplifies many tasks, but its now doing something that I just don’t understand.

When I try to return a TH1F object from a function, its type on the other end has reverted to a “PyROOT_NoneType”. Here’s a stripped down version of the offending code:

#!/usr/bin/python
import sys
from ROOT import TFile, TH1F

def GetGammaE(file_name) :
    f = TFile(file_name)
    hist = TH1F("zzz", "zzz", 8000, -0.5, 7999.5)
    print type(hist)
    return hist

hist = GetGammaE(sys.argv[1])
print type(hist)

The first print statement gives “<class ‘ROOT.TH1F’>” while the second print statement gives “<type ‘PyROOT_NoneType’>”

So, why does returning this object seem to destroy its type? I’ve also noticed that removing the TFile line solves this problem, but of course in the real implementation I need the data in the TFile. :slight_smile: Similarly, using the default constructor

hist = TH1F()

also solves the problem. So I can use this and the SetBins and SetNameTitle functions to accomplish the same task, but I think there is probably a more satisfactory solution?

Thanks in advance for your help!

I’m not sure if this is correct, but it might be due to the histogram’s automatically adding themselves to TFile’s lists of objects and such. Thus when the TFile goes out of scope and closes, it steals away the reference to the TH1. A real expert can correct/clarify this if I am wrong or unclear.

My suggestion is to try to make the histogram as normal, but instead of returning the histogram directly, return a .Clone()'d copy of it. As long as your histograms aren’t crazy big, there should not be much penalty in terms of speed or memory use, since the old histogram is cleaned up right away.

Jean-François

Hi,

yes, Jean-François’ diagnosis is correct. Opening the TFile, changes gDirectory to point to it. The subsequent creation of the histogram associates it with that file. Then, because the file only has a local reference, it gets destroyed at the end of the function. It’s destructor closes the file. A RecursiveRemove() call tells python that the C++ pointer has just become invalid, and so the type is set to something that behaves as None on use (rather than segfaulting, which would be the unpleasant alternative).

As a solution, per the TH1 documentation:[code]When an histogram is created, a reference to it is automatically added to the list of in-memory objects for the current file or directory. This default behaviour can be changed by:

   h->SetDirectory(0);          for the current histogram h
   TH1::AddDirectory(kFALSE);   sets a global switch disabling the reference[/code](I don't think a Clone() will work, as that call will happen before the file is closed.)

Cheers,
Wim