chopper draw lion4
chopper draw lion4

Reputation: 13497

Setting ranges to zero using numpy

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

Answers (2)

Will
Will

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

colcarroll
colcarroll

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

Related Questions