Numpy.ndarray not working in calling TGraph?

Hi,

There is probably an easy solution to my problem. I’m trying to call build TGraph object with numpy ndarrays. This doesn’t work, as in

graphTmplt = TGraph(npointsTmplt,startTime,numTemplates)

where startTime and numTemplates are numpy.ndarray objects. It gives me an error :

TGraph::TGraph(Int_t n, const Float_t* x, const Float_t* y) =>
could not convert argument 2 (‘numpy.ndarray’ object has no attribute ‘typecode’)

What kind of object should I use ? Is there a way to convert numpy.ndarray to Float* ?

Thanks for any hint

Damir

Damir,

which version of ROOT are you using? For older versions, there was a reliance on the datamember ‘typecode’ (as per the python array module) to find the type of the array elements if it could not be inferred from the buffer interface. This has since been improved.

There may be workarounds possible for older versions, but then I’d need to know the one your using …

Cheers,
Wim

Hi Wim,

I think I’m using v5r18 but I’ll check if I didn’t do any mistake.

Cheers

Damir

Damir,

just checked … 5.18 works for me (for my previous posting I used CVS HEAD). If it doesn’t work for you, can you post a script that I can run for testing?

Cheers,
Wim

[code]>>> import numpy

a = numpy.ndarray( [5.] )
for i in range(len(a)):
… a[i] = i

from ROOT import TGraph
b = TGraph( 4, a, a )
b
<ROOT.TGraph object (“Graph”) at 0x88dcb38>

b.Draw()
TCanvas::MakeDefCanvas: created default TCanvas with name c1

[/code]

Hi Wim,

I tried your snippet of code, and it seems to work, but my code still has the same behaviour ! I even printed the version of ROOT to be sure. The data I have is quite big, so I saved the result in two files (I don’t yet know how to “pickle” two objects in the same file). They are attached.

Then I did

import numpy
import pickle
f = file(‘startTime.txt’)
st = pickle.load(f)
f.close()
f = file(‘numTemplates.txt’)
numt = pickle.load(f)
from ROOT import TGraph
gr = TGraph(374,st,numt)

and I get the error

Hope you can do something with these

Cheers

Damir
numTemplates.txt (5.57 KB)
startTime.txt (7.28 KB)

I think I’ve found what is going on. Trying to see what was the difference between the two files I gave above, I noticed there was a string
(S’i4’
in one of them, while it was
(S’f8’

in the other. So I guess that one of the arrays was an array of ints and the other an array of floats. Which is obviously a problem for ROOT to handle.

Maybe the error message is misleading and could be changed ?

Back to learning Python… the hard way !

Anyway, thanks for your help

Damir

Damir,

[back online after travel]

yes, that is the problem (check type(numt[0]). You can do something like numt.astype(‘float’) to get an array with the correct type.

I’ve changed to error message to:could not convert argument 3 ('numpy.ndarray' object has no attribute 'typecode' and given element size (4) does not match needed (8))
(the match would be on double*, double*, so required element size is 8 (i.e. sizeof(double), given is 4 (that is, sizeof(int) ). Note that with a bad type, b/c of the trial of element size (which is calculated from buflenth/nelem), you could end up with a bad match for e.g. float* and int* when sizeof(float) == sizeof(int).

Cheers,
Wim

I have a problem similar to the one posted above. The difference is that I have a numpy array containing float32 data which is read from an external library (which i would prefer not to change). When i try the above code snippet, everything works fine, but the numpy array a is containing float64 data. If i change the snippet to force the numpy array to contain float32 data:

In[8]: import numpy
In[9]: a = numpy.ndarray( [5.],dtype=numpy.float32)

In [10]: for i in range(len(a)):
a[i]=i
…:

In [12]: b = TGraph( 4, a, a )

In [13]: b.Draw(“AL”)

I don’t get any error message, but the absolute scale on the plot is messed up. My guess is that, the resolution of the overloaded TGraph constructor doesn’t work properly, and the data is read using Double_t pointers, or something alike.

Does anyone know a way around this?

edit: as a workaround I’m now using: a = numpy.asarray(a,dtype=numpy.float64) to copy the array to float64.