Bounding box of numpy array with periodic boundary conditions (wrapping) - python

I would like to do something similar to this question, or this other one, but using periodic boundary conditions (wrapping). I'll make a quick example.
Let's say I have the following numpy array:
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 0
0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
Then, by using one of the methods proposed in the two linked questions, I am able to extract the bounding box of non-zero values:
0 0 0 1 1 1 1 1
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
1 1 1 1 0 0 0 0
However, if the non-zero elements "cross" the border and come back on the other side, like so:
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
Then the result is:
1 1 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 1 1 1 1 0 0
which is not what I want. I would like the result to be the same as the previous case. I am trying to figure out an intelligent way to do this, but I am stuck. Anybody have ideas?

We can adapt this answer like so:
import numpy as np
def wrapped_bbox(a):
dims = [*range(1,a.ndim)]
bb = np.empty((a.ndim,2),int)
i = 0
while True:
n = a.shape[i]
r = np.arange(1,2*n+1)
ai = np.any(a,axis=tuple(dims))
r1_a = np.where(ai,r.reshape(2,n),0).ravel()
aux = np.maximum.accumulate(r1_a)
aux = r-aux
idx = aux.argmax()
mx = aux[idx]
if mx > n:
bb[i] = 0,n
else:
bb[i] = idx+1, idx+1 - mx
if bb[i,0] >= n:
bb[i,0] -= n
elif bb[i,1] == 0:
bb[i,1] = n
if i == len(dims):
return bb
dims[i] -= 1
i += 1
# example
x = """
......
.x...-
..x...
.....x
"""
x = np.array(x.strip().split())[:,None].view("U1")
x = (x == 'x').view('u1')
print(x)
for r in range(x.shape[1]):
print(wrapped_bbox(np.roll(x,r,axis=1)))
Run:
[[0 0 0 0 0 0] # x
[0 1 0 0 0 0]
[0 0 1 0 0 0]
[0 0 0 0 0 1]]
[[1 4] # bbox vert
[5 3]] # bbox horz, note wraparound (left > right)
[[1 4]
[0 4]] # roll by 1
[[1 4]
[1 5]] # roll by 2
[[1 4]
[2 6]] # etc.
[[1 4]
[3 1]]
[[1 4]
[4 2]]

Related

Adjacency matrix using numpy

I need to generate the following adjacency matrices:
No of Nodes = 3
A B C AB AC BC
A 0 1 1 0 0 1
B 1 0 1 0 1 0
C 1 1 0 1 0 0
AB 0 0 1 0 0 0
AC 0 1 0 0 0 0
BC 1 0 0 0 0 0
To generate an adjacency matrix for 3 nodes, I can use the code available here, which is
out = np.block([
[1 - np.eye(3), np.eye(3) ],
[ np.eye(3), np.zeros((3, 3))]
]).astype(int)
But it cannot use for different number of nodes, for example if we have 5 nodes then:
No of Nodes = 5
A B C D E AB AC AD AE BC BD BE CD CE DE
A 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1
B 1 0 1 1 1 0 1 1 1 0 0 0 1 1 1
C 1 1 0 1 1 1 0 1 1 0 1 1 0 0 1
D 1 1 1 0 1 1 1 0 1 1 0 1 0 1 0
E 1 1 1 1 0 1 1 1 0 1 1 0 1 0 0
AB 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0
AC 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0
AD 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0
AE 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0
BC 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0
BD 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0
BE 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0
CD 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0
CE 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0
DE 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
Is there any simple and easiest way to implement these adjacency matrices?
Inferring the logic of the output from your two examples, I think something like this might do what you want:
import numpy as np
def make_matrix(N, dtype=int):
n_comb = N * (N - 1) // 2
upper_left = 1 - np.eye(N, dtype=dtype)
lower_right = np.zeros((n_comb, n_comb), dtype=dtype)
cross = np.ones((N, N, N), dtype=dtype)
i = np.arange(N)
cross[i, :, i] = 0
cross[:, i, i] = 0
cross = cross[(np.triu_indices(N, k=1))]
return np.block([[upper_left, cross.T],
[cross, lower_right]])
print(make_matrix(3))
[[0 1 1 0 0 1]
[1 0 1 0 1 0]
[1 1 0 1 0 0]
[0 0 1 0 0 0]
[0 1 0 0 0 0]
[1 0 0 0 0 0]]
print(make_matrix(5))
[[0 1 1 1 1 0 0 0 0 1 1 1 1 1 1]
[1 0 1 1 1 0 1 1 1 0 0 0 1 1 1]
[1 1 0 1 1 1 0 1 1 0 1 1 0 0 1]
[1 1 1 0 1 1 1 0 1 1 0 1 0 1 0]
[1 1 1 1 0 1 1 1 0 1 1 0 1 0 0]
[0 0 1 1 1 0 0 0 0 0 0 0 0 0 0]
[0 1 0 1 1 0 0 0 0 0 0 0 0 0 0]
[0 1 1 0 1 0 0 0 0 0 0 0 0 0 0]
[0 1 1 1 0 0 0 0 0 0 0 0 0 0 0]
[1 0 0 1 1 0 0 0 0 0 0 0 0 0 0]
[1 0 1 0 1 0 0 0 0 0 0 0 0 0 0]
[1 0 1 1 0 0 0 0 0 0 0 0 0 0 0]
[1 1 0 0 1 0 0 0 0 0 0 0 0 0 0]
[1 1 0 1 0 0 0 0 0 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0 0 0 0 0 0 0 0]]
The logic here is that each row of the upper-right matrix is like the flattened upper-triangle of a straightforward NxN matrix. For example:
# construct second row of upper-right matrix for 5x5 case:
x = np.ones((5, 5), dtype=int)
x[1] = 0
x[:, 1] = 0
print(x)
# [[1 0 1 1 1]
# [0 0 0 0 0]
# [1 0 1 1 1]
# [1 0 1 1 1]
# [1 0 1 1 1]]
print(x[np.triu_indices(5, k=1)])
# [0 1 1 1 0 0 0 1 1 1]

Python keeps updating wrong list

I'm trying to create a code to simulate the spread of something, via a 2D list of nxn structure. My issue is this: when I create a temp of my original list via temp = [*board], board[:], etc. it nonetheless updates both lists and instead of returning,
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 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
0 0 0 0 0 0 1 1 1 0 0 0 0 0 0
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 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
returns
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
my code is here:
def spread(board, iterations, size):
temp = board[:]
for iteration in range(iterations):
for x in range(size):
for y in range(size):
if board[x][y] == 1:
if x+1 < size:
temp[x+1][y] = 1
if x-1 >= 0:
temp[x-1][y] = 1
if y+1 < size:
temp[x][y+1] = 1
if y-1 >= 0:
temp[x][y-1] = 1
board = temp[:]
return board
and I called it via
new_board = spread(my_board, 1, 15)
This is programming 101. Remember, lists are stored in heap, with pointers to them.
So really the variable board points to the place in heap where that array is stored. When you assign temp to board, what you are doing is creating a new pointer which points to that same array. I suggest taking a look at this using python tutor: https://pythontutor.com/visualize.html#mode=edit
For example:
b = [1,2,3,4,5]
a = b
a[0] = 2
print(b)
will output
[2,2,3,4,5]
Try it out in python tutor and you'll see what's happening!
To solve your problem, create a deep copy
def deep_copy(board):
temp = []
for i in range(len(board)):
row_copy = []
for j in range(len(board[0])):
row_copy.append(board[i][j])
temp.append(row_copy)
return temp

Efficient majority voting for 1-in-N classification with sliding window classifier over 2D Array

Short version: I would like to use the values in a 2D array to index the third dimension of a corresponding subset of a larger array - and then increment those elements.
I would appreciate help making the two incorporate_votes algorithms quicker. Actually sliding the classifier over the array and calculating optimal strides is not the point here.
Long version:
I have an algorithm, which classifies each element in R1xC1 2D array as 1 of N classes.
I would like to classify a larger 2D array of size R2xC2. Rather than tessellating the larger array into multiple R1xC1 2D arrays I would like to slide the classifier over the larger array, such that each element in the larger array is classified multiple times. This means that I will have a R2xC2xN array to store the results in, and as the window slides across the large array each pixel in the window will increment one of elements in third dimension (i.e. one of the N classes).
After all the sliding is finished we can simply get the argmax in the dimension corresponding to the classification to get the per element classification.
I intend to scale this up to classify an array of several million pixels with a few dozens so I am concerned with the efficiency of using the classification results to increment one value in the classification dimension per element.
Below is the toy version of the problem I have been crafting all evening in Python3. It has a naive double for loop implementation and a slightly better one obtained by index swizzling and some smart indexing. The classifier is just random.
import numpy as np
map_rows = 8
map_cols = 10
num_candidates = 3
vote_rows = 6
vote_cols = 5
def display_tally(the_tally):
print("{:25s}{:25s}{:25s}".format("Class 0", "Class 1", "Class 2"))
for i in range(map_rows):
for k in range(num_candidates):
for j in range(map_cols):
print("{:<2}".format(the_tally[i, j, k]), end='')
print(" ", end='')
print("")
def incorporate_votes(current_tally, this_vote, left, top):
for i in range(vote_rows):
for j in range(vote_cols):
current_tally[top + i, left + j, this_vote[i, j]] += 1
return current_tally
def incorporate_votes2(current_tally, this_vote, left, top):
for i in range(num_candidates):
current_tally[i, top:top + vote_rows, left:left + vote_cols][this_vote == i] += 1
return current_tally
tally = np.zeros((map_rows, map_cols, num_candidates), dtype=int)
swizzled_tally = np.zeros((num_candidates, map_rows, map_cols), dtype=int)
print("Before voting")
display_tally(tally)
print("\n Votes from classifier A (centered at (2,2))")
votes = np.random.randint(num_candidates, size=vote_rows*vote_cols).reshape((vote_rows, vote_cols))
print(votes)
tally = incorporate_votes(tally, votes, 0, 0)
swizzled_tally = incorporate_votes2(swizzled_tally, votes, 0, 0)
print("\nAfter classifier A voting (centered at (2,2))")
display_tally(tally)
print("\n Votes from classifier B (Centered at (5, 4))")
votes2 = np.random.randint(num_candidates, size=vote_rows*vote_cols).reshape((vote_rows, vote_cols))
print(votes2)
tally = incorporate_votes(tally, votes2, 3, 2)
swizzled_tally = incorporate_votes2(swizzled_tally, votes2, 3, 2)
print("\nAfter classifier B voting (Centered at (5, 4))")
print("Naive vote counting")
display_tally(tally)
print("\nSwizzled vote counting")
display_tally(np.moveaxis(swizzled_tally, [-2, -1], [0, 1]))
new_tally = np.moveaxis(tally, -1, 0)
classifications = np.argmax(swizzled_tally, axis=0)
print("\nNaive classifications")
print(classifications)
print("\nSwizzled classifications")
classifications = np.argmax(tally, axis=2)
print(classifications)
And some sample output:
Before voting
Class 0 Class 1 Class 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Votes from classifier A (centered at (2,2))
[[1 1 2 2 1]
[0 2 0 2 1]
[0 2 2 0 2]
[1 1 1 2 0]
[1 0 0 2 1]
[2 1 1 1 0]]
After classifier A voting (centered at (2,2))
Class 0 Class 1 Class 2
0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Votes from classifier B (Centered at (5, 4))
[[2 2 2 0 0]
[0 1 2 1 2]
[2 0 0 2 0]
[2 2 1 1 1]
[1 2 0 2 1]
[1 1 1 1 2]]
After classifier B voting (Centered at (5, 4))
Naive vote counting
Class 0 Class 1 Class 2
0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0
1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0
0 1 1 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 1 1 0 1 1 1 0 0 1 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0
Swizzled vote counting
Class 0 Class 1 Class 2
0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0
1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0
0 1 1 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 1 1 0 1 1 1 0 0 1 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0
Naive classifications
[[1 1 2 2 1 0 0 0 0 0]
[0 2 0 2 1 0 0 0 0 0]
[0 2 2 0 2 2 0 0 0 0]
[1 1 1 0 0 2 1 2 0 0]
[1 0 0 2 0 0 2 0 0 0]
[2 1 1 1 0 1 1 1 0 0]
[0 0 0 1 2 0 2 1 0 0]
[0 0 0 1 1 1 1 2 0 0]]
Swizzled classifications
[[1 1 2 2 1 0 0 0 0 0]
[0 2 0 2 1 0 0 0 0 0]
[0 2 2 0 2 2 0 0 0 0]
[1 1 1 0 0 2 1 2 0 0]
[1 0 0 2 0 0 2 0 0 0]
[2 1 1 1 0 1 1 1 0 0]
[0 0 0 1 2 0 2 1 0 0]
[0 0 0 1 1 1 1 2 0 0]]

Find nearest item given an angle in 2D numpy array

Given a numpy 2D array, what would be the best way to get the nearest item (for this example '1') from a specified coordinate (where 'X' is located) given an angle.
For example, lets say we have 'X' located at (1,25) in a 2D array shown below. Say with an angle 225 degrees, assuming 0 degrees goes straight to the right and 90 degrees goes straight up. How can I get the nearest coordinate of a '1' located towards that vector direction?
[
0000000000000000000000000000
0000000000000000000000000X00
0000000000000000000000000000
1110000000000000000000000000
1111100000000000000000000000
1111110000000000000000000000
1111111000000000000000000000
1111111110000000000000000000
1111111111100000000000000000
]
I'm assuming by towards that direction you mean something like on that ray. In that case 255° has no solution so I took the liberty of changing that to 195°.
You could then brute-force it:
import numpy as np
a = """
0000000000000000000000000000
0000000000000000000000000X00
0000000000000000000000000000
1110000000000000000000000000
1111100000000000000000000000
1111110000000000000000000000
1111111000000000000000000000
1111111110000000000000000000
1111111111100000000000000000
"""
a = np.array([[int(i) for i in row] for row in a.strip().replace('X', '2').split()], dtype=np.uint8)
x = np.argwhere(a==2)[0]
y = np.argwhere(a==1)
d = y-x
phi = 195 # 255 has no solutions
on_ray = np.abs(d#(np.sin(np.radians(-phi-90)), np.cos(np.radians(-phi-90))))<np.sqrt(0.5)
show_ray = np.zeros_like(a)
show_ray[tuple(y[on_ray].T)] = 1
print(show_ray)
ymin=y[on_ray][np.argmin(np.einsum('ij,ij->i', d[on_ray], d[on_ray]))]
print(ymin)
Output:
# [[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
# [6 6]

Check if every section of matrix is all 0 using numpy

I want to check if all entries of a matrix A within 10 indices of a given entry (x,y) are zero. I think something like this should do it
(numpy.take(A,[x-10:x+10,y-10:y+10]) == 0).all()
but I'm getting a invalid syntax error. Think I'm not constructing the index ranges right, any suggestions?
Don't worry about using take, just index your array like this:
(A[x-10:x+10,y-10:y+10] == 0).all()
A simple boolean check against the entries of the submatrix will do
np.all(A[x-10:x+11,y-10:y+11]==0)
(note the upper index is not included, so I changed to i-10:i+11)
Suppose A is an array of shape (19,19):
import numpy as np
H = W = 19
x, y = 1, 1
N = 10
A = np.random.randint(10, size=(H,W))
Then
In [433]: A[x-N:x+N,y-N:y+N]
Out[433]: array([[4]])
Since x-N is 1-10 = -9, A[x-N:x+N,y-N:y+N] is equivalent to A[-9:11,-9:11],
which is equivalent to A[19-9:11,19-9:11] which is the same as A[10:11,10:11].
So only one value is selected.
That's not giving you "all entries of a matrix A within 10 indices of a given
entry (x,y)".
Instead, you could generate the desired subregion using a boolean mask:
X, Y = np.ogrid[0:H,0:W]
mask = (np.abs(X - x) < N) & (np.abs(Y - y) < N)
Once you have the mask, you can select the subregion where the mask is True using A[mask], and test if every value is zero with
(A[mask] == 0).all()
import numpy as np
np.random.seed(2015)
H = W = 19
x, y = 1, 1
N = 10
A = np.random.randint(10, size=(H,W))
print(A[x-N:x+N,y-N:y+N])
# [[4]]
X, Y = np.ogrid[0:H,0:W]
mask = (np.abs(X - x) < N) & (np.abs(Y - y) < N)
print(mask.astype(int))
# [[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 0 0 0 0 0 0 0 0]
# [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 0 0 0 0 0 0 0 0]
# [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 0 0 0 0 0 0 0 0]
# [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 0 0 0 0 0 0 0 0]
# [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 0 0 0 0 0 0 0 0]
# [1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
print(A[mask] == 0).all()
# False

Categories