In [588]: x,y=np.ogrid[-1:1:5*1j,-1:1:5*1j]
In [589]: z=x*y*1j
In [590]: def setcolor(z):
return (z.real,z.imag,np.abs(z))
.....:
In [591]: fn=np.frompyfunc(setcolor,1,1)
In [592]: fn(z)
Out[592]:
array([[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None]], dtype=object)
which turns to an array of 0s with .astype(float)
. Here setcolor
is just a simple way of getting 3 numbers from a complex input. You can choose something more realistic.
But if we give it the correct out
count, we get a tuple of arrays.
In [593]: fn=np.frompyfunc(setcolor,1,3)
In [594]: fn(z)
Out[594]:
(array([[0.0, 0.0, -0.0, -0.0, -0.0],
[0.0, 0.0, -0.0, -0.0, -0.0],
[-0.0, -0.0, 0.0, 0.0, 0.0],
[-0.0, -0.0, 0.0, 0.0, 0.0],
[-0.0, -0.0, 0.0, 0.0, 0.0]], dtype=object),
array([[1.0, 0.5, 0.0, -0.5, -1.0],
[0.5, 0.25, 0.0, -0.25, -0.5],
[0.0, 0.0, 0.0, 0.0, 0.0],
[-0.5, -0.25, 0.0, 0.25, 0.5],
[-1.0, -0.5, 0.0, 0.5, 1.0]], dtype=object),
array([[1.0, 0.5, 0.0, 0.5, 1.0],
[0.5, 0.25, 0.0, 0.25, 0.5],
[0.0, 0.0, 0.0, 0.0, 0.0],
[0.5, 0.25, 0.0, 0.25, 0.5],
[1.0, 0.5, 0.0, 0.5, 1.0]], dtype=object))
It could be turned in to a (3,N,N) array with:
np.array([A.astype(float) for A in fn(z)])
You'd have to do a transpose to make a (N,N,3) array.
For this small sample it isn't faster
In [599]: timeit np.array([A.astype(float) for A in fn(z)]).transpose([1,2,0])
1000 loops, best of 3: 664 µs per loop
In [603]: %%timeit
.....: img=np.zeros((5,5,3),float)
.....: for i in range(5):
for j in range(5):
img[i,j]=setcolor(z[i,j])
.....:
1000 loops, best of 3: 316 µs per loop
In some other SO questions I found that frompyfunc
is faster than vectorize
, and a modest improvement over direct iteration.
This is faster - but it doesn't do the job
In [606]: timeit np.frompyfunc(setcolor,1,1)(z).astype(float)
10000 loops, best of 3: 25.6 µs per loop
The setcolor
that I chose can take the array z
directly, resulting in a fast 3d array creation.
In [608]: timeit np.array([A.astype(float) for A in setcolor(z)]).transpose([1,2,0])
10000 loops, best of 3: 47.1 µs per loop
From https://stackoverflow.com/a/29703463/901925, an earlier answer involving frompystack
, I find that vstack
is a faster way to assemble a tuple into a 3d array:
In [616]: timeit np.vstack(fn(z)).astype(float).reshape(3,5,5).transpose([1,2,0])
10000 loops, best of 3: 178 µs per loop
So done right, frompyfunc
can give about a 2x speedup over explicit iteration, but still not as good as function that handles arrays directly.