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]
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).