4

This question is related to: How to apply a disc shaped mask to a numpy array?

From the solution: https://stackoverflow.com/a/8650741/4484153, is it possible to obtain circular mask in the following manner:

>>> new_arr
array([[ True,  True,  True,  True,    1.,  1.,  1.,  True],
       [ True,  True,  True,  True,  True,  1., True, True],
       [ True,  True,  True,  True,    1.,  1.,  1.,  True],
       [ True,  True,  True,  True,    1.,  1.,  1.,  True],
       [ 1.,    True,    1.,    1.,    1.,  1.,  1.,  1.  ],
       [ 1.,      1.,    1.,    1.,    1.,  1.,  1.,  1.  ],
       [ 1.,    True,    1.,    1.,    1.,  1.,  1.,  1.  ],
       [ True,  True,  True,  True,    1.,  1.,  1.,  True]])

in such a way that the array wraps around its columns and rows?

BSMP
  • 4,596
  • 8
  • 33
  • 44
MisterJ
  • 71
  • 5

2 Answers2

3

One way could just be to create the mask of required size in the center of the array and then use np.roll to shift the mask along an axis (this causes the mask to wrap around the edges of the array).

Following the method in the linked question and answer:

ones = np.ones((8, 8))

a, b = 3, 3
n = 8
r = 3
mask = x**2 + y**2 <= r**2

constructs mask like this:

array([[False, False, False,  True, False, False, False, False],
       [False,  True,  True,  True,  True,  True, False, False],
       [False,  True,  True,  True,  True,  True, False, False],
       [ True,  True,  True,  True,  True,  True,  True, False],
       [False,  True,  True,  True,  True,  True, False, False],
       [False,  True,  True,  True,  True,  True, False, False],
       [False, False, False,  True, False, False, False, False],
       [False, False, False, False, False, False, False, False]], dtype=bool)

Then rolling mask two places up and two places left and using it on ones...

>>> rolled_mask = np.roll(np.roll(mask, -2, axis=0), -2, axis=1)
>>> ones[rolled_mask] = 255
>>> ones
array([[ 255.,  255.,  255.,  255.,    1.,    1.,    1.,  255.],
       [ 255.,  255.,  255.,  255.,  255.,    1.,  255.,  255.],
       [ 255.,  255.,  255.,  255.,    1.,    1.,    1.,  255.],
       [ 255.,  255.,  255.,  255.,    1.,    1.,    1.,  255.],
       [   1.,  255.,    1.,    1.,    1.,    1.,    1.,    1.],
       [   1.,    1.,    1.,    1.,    1.,    1.,    1.,    1.],
       [   1.,  255.,    1.,    1.,    1.,    1.,    1.,    1.],
       [ 255.,  255.,  255.,  255.,    1.,    1.,    1.,  255.]])
Alex Riley
  • 169,130
  • 45
  • 262
  • 238
  • Thanks ajcr. It looks like what I would need :) Only concern is I will have to apply this masking at each element, so might take bit of computational time(I will be working with huge arrays). Dont have enough rep, otherwise would have voted up. – MisterJ Jan 22 '15 at 21:17
  • No problem, glad it was useful! One concern is that `np.roll` produces a new array in memory - if the masks are huge this isn't desirable (but should still be workable). There may be a more memory-efficient mathematical way to select the required indices. I'll post an update to the answer if anything significantly better occurs to me... – Alex Riley Jan 22 '15 at 21:29
  • @MisterJ: It sounds like you might be looking for a [scipy.ndimage.filters function](http://docs.scipy.org/doc/scipy/reference/ndimage.html#module-scipy.ndimage.filters).There are some examples using the generic_filter in [the tutorial](http://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html#generic-filter-functions). Note in particular the `footprint` parameter, which would allow you to pass *one* circular mask and have scipy shift it around for you. – unutbu Jan 22 '15 at 21:31
1

If you want to create the mask directly, the following works:

>>> N = 10
>>> row, col = 8, 7
>>> radius = 4
>>> rows = np.arange(N) - row
>>> rows = np.minimum(np.abs(rows), rows % N)
>>> cols = np.arange(N) - col
>>> cols = np.minimum(np.abs(cols), cols % N)
>>> (rows[:, None]**2 + cols**2 <= radius**2).astype(int)
array([[1, 0, 0, 0, 1, 1, 1, 1, 1, 1],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
       [1, 0, 0, 0, 1, 1, 1, 1, 1, 1],
       [1, 0, 0, 0, 1, 1, 1, 1, 1, 1],
       [1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
       [1, 0, 0, 0, 1, 1, 1, 1, 1, 1]])
Jaime
  • 65,696
  • 17
  • 124
  • 159
  • Thanks Jaime, I will try this one out also :) This might help me to reduce the computational time as it is applying directly. – MisterJ Jan 23 '15 at 00:07