0

I really just can't grok how masks work in Numpy.

I create a mask like

import numpy
def make_mask(center_x,center_y,len_x,len_y):
      x,y = numpy.ogrid[:len_x, :len_y]
      mask = (center_x-x)**2 + (center_y-y)**2
      return mask

Then I attempt to use it

 >>>a = numpy.ones((10,10))
 >>>mask = make_mask(2,2,2,2,2)
 >>>a[mask] = 0
 >>>a
 array([[1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1],
        [0,0,0,0,0,0,0,0],
        [1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1],
        [0,0,0,0,0,0,0,0],
        [1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1],
        [0,0,0,0,0,0,0,0]])

What I was expecting was something like

 >>>a
 array([[1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1],
        [1,1,0,0,1,1,1,1],
        [1,1,0,0,1,1,1,1],
        [1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1]])

I've try a few different versions of the function. I just can't get the desired behavior. What am I doing wrong. I really don't understand how a 2D matrix indexes a 2D matrix.

Valarauca
  • 1,041
  • 3
  • 10
  • 23
  • 1
    Could you post all of your code? Currently, your `make_mask` function does not define `center_x` or `center_y` and will not work as provided. Unless you meant for `center_x` and `center_y` to be `index_x` and `index_y`. Either way, it doesn't work the way you provided it. – Brady Sheehan Jun 16 '16 at 13:13
  • 1
    Also, there is a fifth parameter in your `make_mask` call. – Benjamin Jun 16 '16 at 13:15
  • But, I think what you are looking for is slice notation: http://stackoverflow.com/questions/509211/explain-pythons-slice-notation. I would checkout this link, I believe this will help. – Brady Sheehan Jun 16 '16 at 13:19
  • Editted the code. That is all my code. This is something I'm tooling up in the RPEL. Sorry for the miss named variables. It was an honest mistake. Also I understand slice notation. The issue is I don't understand how a 2D matrix indexes a 2D matrix. You have to understand its really hard to ask for help on something that feels like magic. Take this for example: https://stackoverflow.com/questions/8647024/how-to-apply-a-disc-shaped-mask-to-a-numpy-array same issue what is the 2D array doing indexing a 2D array? – Valarauca Jun 16 '16 at 13:30

2 Answers2

3

Your mask is setting the 2nd, 5th and 8th rows to 0; the array is being flattened since it does not have the same shape as the array it is masking. It is being applied as:

a[2] = 0
a[5] = 0
a[8] = 0

I think you were expecting something more like:

mask = numpy.ones_like(a)
mask[center_y:center_y + len_y, center_x:center_x + len_x] = 0

which has the same size as the array you are tring to mask and gives the expected result.

Benjamin
  • 11,560
  • 13
  • 70
  • 119
1

If you take a look at what your make_mask function does, when written like this:

def make_mask(index_x,index_y,len_x,len_y):
      x,y = numpy.ogrid[:len_x, :len_y]
      mask = (index_x-x)**2 + (index_y-y)**2
      return mask

you will see that you get

array([[8, 5],
       [5, 2]])

and when you index a 10x10 matrix with that 2x2 matrix, I believe it treats all the values in that matrix as indexing the larger matrix by row. Which is why you see the 2nd row with all zeros, the 5th row with all zeros and the 8th row with all zeros.

To get the effect you desire, you can just use the indices you have, you don't even need a function:

a[startx:startx+lenx, starty:starty+leny] = 0

which gives:

array([[ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  0.,  0.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  0.,  0.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.]])
Brady Sheehan
  • 162
  • 2
  • 12