Convert TH3 buffer to numpy array

I am trying to read a TH3 histogram into a numpy array. I have the following method working, but it is rather slow:

ROOT.TFile(filename, 'r') h = f.Get(objname) Nx = h.GetNbinsX() Ny = h.GetNbinsY() Nz = h.GetNbinsZ() binvals = np.zeros((Nx,Ny,Nz)) for i in range(Nx): for j in range(Ny): for k in range(Nz): binvals[i,j,k] = h.GetBinContent(i+1,j+1,k+1) # +1 to skip underflow bins

I am wondering if there is a faster way this can be done, by accessing the underlying C array? I have tried reading from the output of GetBuffer, but I get only either gibberish or zeros:

buf = h.GetBuffer()
print buf
a = list(buf)
print a
print a[:100]

output:

<Double_t buffer, size 2147483647>
S�tA@s @s
[]
[]

Is there a standard way to do this?

Hi,

yes there is:

import ROOT
import numpy

h = ROOT.TH3F("","",4,-2,2,4,-2,2,4,-2,2)
h.FillRandom("gaus")

arr = h.GetArray()

npa = numpy.ndarray( (4*4*4,),dtype= numpy.float32, buffer=arr)
print npa

Cheers,
D

Ahh amazing, thanks!

For future readers: I struggled a little to transform the linearised array back into the correct 3D shape, so here is the code to get it done:

    f = ROOT.TFile(filename, 'r')
    obj = f.Get(objname)
    obj.SetDirectory(0) # decouple object from the root file so that it doesn't get destroyed when the file closes
    h = get_ROOT_obj(filename,name,verbose)
    Nx = h.GetNbinsX()
    Ny = h.GetNbinsY()
    Nz = h.GetNbinsZ()

    # Get underlying array and convert it to a numpy array
    arr = h.GetArray()
    binvals = np.ndarray( ((Nx+2)*(Ny+2)*(Nz+2),), dtype=np.float32, buffer=arr)
    binvals = np.transpose(binvals.reshape((Nz+2,Ny+2,Nx+2),order='C'),(2,1,0))
    # Strip off underflow and overflow bins
    binvals = binvals[1:-1,1:-1,1:-1]

The output dimensions are then in the “natural” order (x,y,z).

Thanks for contributing back your code!

D