array2tree error
ascarff opened this issue · 18 comments
Hi,
I'm using a combination of tree2array, doing some stuff to the array and then converting back with array2tree. The tree2array side works fine but I can't convert back again I get the error: "TypeError: object of type 'NoneType' has no len()".
The section of code I'm using is below, with 'det' being my TTree and 'HVvolts' being one of the branches. The array modHV is calculated correctly and gives me what I need. I just can't convert it back to a branch of my TTree.
import numpy
from root_numpy import tree2array, array2tree
HV = tree2array(det,branches = "HVvolts")
t_c = 0.83
modHV = (numpy.mod(-HV,t_c))
print "length of modHV:",len(modHV)
print "modHV type:",type(modHV)
array2tree(modHV,tree=det)
This prints out:
length of modHV: 113385
modHV type: <type 'numpy.ndarray'>
Then the error:
TypeErrorTraceback (most recent call last)
<ipython-input-6-b65205e494d9> in <module>()
7 print "length of modHV:",len(modHV)
8 print "modHV type:",type(modHV)
----> 9 array2tree(modHV,tree=zip4)
/usr/local/lib/python2.7/site-packages/root_numpy/_tree.pyc in array2tree(arr, name, tree)
569 else:
570 incobj = None
--> 571 cobj = _librootnumpy.array2tree_toCObj(arr, name=name, tree=incobj)
572 return ROOT.BindObject(cobj, 'TTree')
573
root_numpy/src/tree.pyx in _librootnumpy.array2tree_toCObj (root_numpy/src/_librootnumpy.cpp:716)()
root_numpy/src/tree.pyx in _librootnumpy.array2tree (root_numpy/src/_librootnumpy.cpp:701)()
root_numpy/src/tree.pyx in _librootnumpy.array2tree (root_numpy/src/_librootnumpy.cpp:673)()
TypeError: object of type 'NoneType' has no len()
So the object has both a type (numpy.ndarray) and a length (113385). Does anyone know what I'm doing wrong here?
Thanks!
What does modHV.dtype
give you? And did you check that none of the values are None
?
modHV.dtype
gives dtype('float64')
. The original branch were doubles so that's as expected. None of the values are None
.
This is a dumb sanity check, but can you try
array2tree(modHV)
instead and see if that works? I guess I'm confused because of this line
array2tree(modHV,tree=zip4)
and I'm not sure where zip4
comes from.
Ah sorry, that should be array2tree(modHV,tree=det)
, I tried with a couple of different trees and must've missed one when changing some bits at the end.
I get the same error when I do array2tree(modHV)
.
Which version of root_numpy
are you using?
Also, can you run
modHV.dtype.names
and modHV.dtype.fields
? I suspect you might not have any field names, which might cause this error...
I'm on root_numpy-4.7.3.
Both modHV.dtype.names
and modHV.dtype.fields
give no result!
Both modHV.dtype.names and modHV.dtype.fields give no result!
There's your problem. You need to specify column names here. What you have is basically a list of values that you're asking to be converted to a TTree.. but we don't know what to set the branch names to. Specifically, the code is failing on this line (https://github.com/scikit-hep/root_numpy/blob/master/root_numpy/src/tree.pyx#L673) which does need some protection. Try something like..
modHV.dtype.names = ['HVvolts_modified']
before passing to the array2tree
call.
Then is says: ValueError: there are no fields defined
. Do I need to put something for modHV.dtype.names
too?
Looks like you need to force it with something like
modHV.dtype = [('HVvolts_modified', 'float64')]
(Note this is now a numpy
issue rather than a root_numpy
problem.)
Ok, so now I'm using:
import numpy
from root_numpy import tree2array, array2tree
HV = tree2array(zip4,branches = "HVvolts")
t_c = 0.83
modHV = (numpy.mod(-HV,t_c))
modHV.dtype = [('HVvolts_modified', 'float64')]
modHV.dtype.names = ['HVvolts_modified']
array2tree(modHV,tree=zip4)
And I get:
<ROOT.TTree object ("zip4") at 0x7fbc27fb1e50>
Error in <TBranch::TBranch::WriteBasketImpl>: basket's WriteBuffer failed.
Error in <TBranch::TBranch::Fill>: Failed to write out basket.
With the errors repeated multiple times
Yes, because I don't think you can write out to the same tree that already exists if you open in READ
only mode... You can do this:
newTree = array2tree(modHV)
and it should work as expected with newTree
. If you want to add a new branch to an existing tree, you need to make sure you're opening the file in RECREATE
/UPDATE
mode to allow you to write out to the existing tree in memory. See #224 for an example of how to do it. Specifically:
import numpy, root_numpy
from rootpy.io import root_open
root_numpy.array2root(numpy.array(numpy.random.random([1000, 2]), dtype=[('a', 'float64'), ('b', 'float64')] ),
'test.root', mode='recreate')
with root_open('test.root', mode='a') as myfile:
new_column = numpy.array(numpy.ones([1000, 1]) , dtype=[('new', 'f8')])
root_numpy.array2tree(new_column, tree=myfile.tree)
myfile.write()
Hmm, it actually seems to be working adding it to a new tree. It just throws up these errors. They are still there when I tried newTree = array2tree(modHV)
. I'm not sure what the error is actually saying.
I suspect because it's just creating the tree in memory instead of being able to write to an open, writeable file. Can you check whether you open the file for reading or reading+writing?
Ah ok, yeah, that might be it. My current code is:
file = ROOT.TFile.Open("datafile.root")
Try
file = ROOT.TFile.Open("datafile.root", "UPDATE")
Ok, that has done it! Thank you very much for all the help and such quick replies! 😃