Reputation: 13497
I began independently learning numpy using the numpy cookbook. I reviewed and executed the following code:
import scipy.misc
import matplotlib.pyplot
#This script demonstates fancy indexing by setting values
#On the diagnols to 0
#Load lena array
lena = scipy.misc.lena()
xmax = lena.shape[0]
ymax = lena.shape[1]
#Fancy indexing
#can set ranges of points to zero, all at once instead of using loop
lena[range(xmax), range(ymax)] = 0
lena[range(xmax-1,-1,-1), range(ymax)] = 0
matplotlib.pyplot.imshow(lena)
matplotlib.pyplot.show()
I understand everything in this code except:
lena[range(xmax), range(ymax)] = 0
lena[range(xmax-1,-1,-1), range(ymax)] = 0
I read the documentation on indexing and slicing but still cannot make sense of the above code. Here is are my points of confusion:
1)range(xmax) and range(ymax) encompass the entire x,y axes. Wouldn't setting them to zero make the entire image black?
2)What does range(xmax-1,-1,-1) mean?
Thanks guys!
Upvotes: 1
Views: 1933
Reputation: 1551
'range' will give you a list. Try it in your REPL and see what happens:
r = range(5)
# r is no [0,1,2,3,4]
So doing 'lena[range(xmax), range(ymax)] = 0' will set the diagonal of the 'lena' matrix to zero since you're stepping through the x and y coordinates incrementally at the same time.
'range' is quite simple. The answer from @JLLagrange answers it perfectly.
Upvotes: 2
Reputation: 3682
The first bit of code is actually misleading, and relies on the fact that lena
is a square image: what happens is equivalent to calling zip(range(xmax), range(ymax))
, and then setting each of the resulting tuples to 0
. You can see what could go wrong here: if xmax != ymax
, then things won't work:
>>> test = lena[:,:-3]
>>> test.shape
(512, 509)
>>> xmax, ymax = test.shape
>>> test[range(xmax), range(ymax)] = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: shape mismatch: objects cannot be broadcast to a single shape
It would probably be better to define diag_max = min(xmax, ymax)
, and then set lena[range(diag_max), range(diag_max)] = 0
.
The answer to your second question is easier: range(from, to, step)
is the general call to range
:
>>> range(1, 10, 2)
[1, 3, 5, 7, 9]
>>> range(1, 10, -2)
[]
>>> range(10, 1, -2)
[10, 8, 6, 4, 2]
>>> range(10, 0, -1)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
In particular, this reverses the previous list, and so grabs the diagonal from right to left instead of left to right.
Upvotes: 2