Reputation: 1503
I am currently learning SciPy
and I want to play a little bit with pylab
and matplotlib
so as an exercise I tried to visualize Reddit
's hot
function.
Of course this code is not working, and I can't really figure out how to google what I want.
from pylab import *
import numpy as np
def f(t,v):
y = lambda a : 1 if a > 0 else (-1 if a < 0 else 0)
z = lambda a : log10(abs(a)) if abs(a) >= 1 else log10(1)
return map(z,v)*map(y,v) + t
n = 256
x = np.linspace(0,100,n)
y = np.linspace(-50,+50,n)
X,Y = np.meshgrid(x,y)
contourf(X, Y, f(X,Y), 15, alpha=.75, cmap='jet')
C = contour(X, Y, f(X,Y), 15, colors='black', linewidth=.5)
show()
EDIT: By not working it means that it is giving me the following error message:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-33-a1d2f439ebda> in <module>()
13 X,Y = np.meshgrid(x,y)
14
---> 15 contourf(X, Y, f(X,Y), 15, alpha=.75, cmap='jet')
16 C = contour(X, Y, f(X,Y), 15, colors='black', linewidth=.5)
17 show()
<ipython-input-33-a1d2f439ebda> in f(t, v)
6 z = lambda a : log10(abs(a)) if abs(a) >= 1 else log10(1)
7
----> 8 return map(z,v)*map(y,v) + t
9
10 n = 256
<ipython-input-33-a1d2f439ebda> in <lambda>(a)
4 y = lambda a : 1 if a > 0 else (-1 if a < 0 else 0)
5
----> 6 z = lambda a : log10(abs(a)) if abs(a) >= 1 else log10(1)
7
8 return map(z,v)*map(y,v) + t
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Upvotes: 0
Views: 193
Reputation: 32521
The error is from if a > 0
, as the error says the truth value of a
, which will be a NumPy array is ambiguous.
Why is a
a NumPy array rather than a single entry? Python's map
does not iterate over each element of the array, it will iterate over one dimension only and your input is multidimensional:
>>> a = np.arange(12).reshape(3, 4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> f = lambda x : x
>>> map(f, a)
[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([ 8, 9, 10, 11])]
You could use np.vectorize
instead of map
, which will work as you want, but you should really be using vectorized NumPy functions on NumPy arrays, where the iteration will be handled by fast native code. Here's how to write your code in this way:
import numpy as np
from pylab import *
def f(t,v):
# reproduce "y" with vectorized functions
temp_a = np.sign(v)
# reproduce "z" with vectorized functions
temp_b = np.log10(np.maximum(np.abs(v), 1.0))
# could also do something like
# abs_v = np.abs(v)
# temp_b = np.where(abs_v >= 1, np.log10(abs_v), np.log10(1))
return temp_a * temp_b + t
n = 256
x = np.linspace(0,100,n)
y = np.linspace(-50,+50,n)
X,Y = np.meshgrid(x,y)
contourf(X, Y, f(X,Y), 15, alpha=.75, cmap='jet')
C = contour(X, Y, f(X,Y), 15, colors='black', linewidth=.5)
show()
Recommended reading:
I would also suggest not using pylab
but importing the modules you need explicitly. e.g. here you would do import matplotlib.pyplot as plt
and use plt.contour
and plt.show()
. See Pylab discussion here and here.
Upvotes: 2