Arrays in branches

Hi
I am trying to fill a tree with some simple branches according to a dictionary and keys. This works just fine:

class myROOTmod:

[i] def init(self,keys,treeName,arr1,arr2):
“”"
this is the init routine
keys is the list of variables
n is the number of different branches we will need to create
“”"
self.keys=keys
self.treeName=treeName # every packet will have its own tree name
# some of the packes have arrays.
self.nv = len(self.keys) # number of variables which will also be number of
self.array1=arr1
self.array2=arr2
# branches
self.Make_Tree() # we just create a tree whenn we call root_manager
self.branchDict={}

def Make_Tree(self):

    # create the tree
self.title = " tree %s with %d variables" %(self.treeName,self.nv)
self.tree=R.TTree(self.treeName,self.title)
# Create a list of arrays o length 0
    self.var_address=[]
    for i in range(self.nv):
        self.var_address.append(array('L',[0]))

# create a list
self.variable_name=[]
self.variable_type=[]
for k in range(self.nv):
        	self.variable_name.append(self.keys[k])
        	self.variable_type.append(self.variable_name[k]+"/i")


    for k in range(self.nv):
        self.tree.Branch(self.variable_name[k],self.var_address[k], self.variable_type[k])[/i]

[/i]
When I am trying to add branches with arrays; I am having problems:

[i] def Append_Branch(self,keys):
“”"
add branches to existing tree
“”"
self.keys1=keys
self.variable_name1=[]
self.variable_type1=[]
self.var_address1=[]
self.nv1 = len(self.keys1) # number of variables which will also be number of
for i in range(self.nv1):
self.var_address1.append(array(‘L’,[0]))

if (self.array1>0) and (self.array2 == 0):
	for k in range(self.nv1):
        		self.variable_name1.append(self.keys1[k])
		temp="[%d]"%(self.array1)
		print self.keys1, self.variable_name1[k]
        		self.variable_type1.append(self.variable_name1[k]+temp+"/i")


create array of array
self.var_address1[k]=num.zeros((1,32),num.int64)
    for k in range(self.nv1):

        self.tree.Branch(self.variable_name1[k],self.var_address1[k], self.variable_type1[k])

[/i]
It works fine to here, but when I fill the tree

[i] def Tree_Fill1(self,array1):
“”"
fill tree with array
“”"

#for i in range(0,32):
self.var_address1[0]=array1
print self.tree.Fill()[/i]

the content of the branch is garbage.
Any good suggestions or hints?
Thanks , andi

[/i]
tree_example.py (2.77 KB)

Andi,

this: “self.var_address1[0]=array1” does not copy the values of the array, but replaces the old array in the list with a new one. The TTree, however, still holds on to the address of the old array.

Best is to assign directly to self.var_address1[0] (etc.).

Cheers,
Wim

Hi Wim
I am probably too ignorant, but I am not sure I understand your
response. What I will am trying to do with the tree fill, is to call it from another
python program and just pass it that array.
If I understand you correctly, I would have to assign then in the calling
python program the values to

Tree_example.var_address1[0],
where I would have to import the tree_example.py as Tree_example
Is that correct?
Thanks for your help,
Andi

Andi,

sorry, can’t say I completely follow you. In particular, I don’t see how you intend to pass the array between two programs? Let me try again with what appears, to me anyway, to be the basic problem. In this line: self.tree.Branch(self.variable_name1[k],self.var_address1[k], self.variable_type1[k])
you hand the tree the address of the array at self.var_address1. From there, a TTree::Fill() call will look for the values to fill the tree at that address (although it’s not obvious to me that the proper size is given this way, as I don’t quite follow the self.variable_type1; from the looks of it, it seems to me that only the first value will be used).

Later in your code, you do:self.var_address1[0]=array1
Now on the python side, the new first entry of the var_address1 list points to the new array1, but the TTree still only knows about the old array, and the memory of the old array has been left untouched. When writing the tree, it is the old array memory that is written out.

One way around this, is to assign all the values one by one:for i in range(len(array1)): self.var_address1[0][i]=array1[i]
Another is to give the address of the new array to the tree (but then you need to be sure the new array is being kept alive as well), using the SetBranchAddress() function.

Cheers,
Wim

Hi Wim
Thanks for your help. Using your suggestion of

for i in range(len(array1)):
self.var_address1[0][i]=array1[i]

together with declaring self.var_address1 a NUMPY twodimensional array got it to work.
Thanks again and cheers,
andi

For C++, I usually let this go…

For Python code, you really want to use the [ code ] and [ / code ] delimiters. As Python uses indenting, it changes the meaning of code to lose that indenting, so

[i]for i in range(len(array1)):
self.var_address1[0][i]=array1

doesn’t work so well, but

for i in range(len(array1)):
   self.var_address1[0][i]=array1[i]

Is great.

Cheers,
Charles