I have a NxN array, e.g.
test_arr = np.arange(25).reshape((5, 5))
I have two points, e.g. r_vals = (0, 1)
, c_vals = (2, 0)
.
The goal is to extract a neighborhood (nearest-neighbor, i.e. 4 values) for both points in the fastest way possible.
That is, I know I could do sth. like
nearest_neighs = [[max(c, 0), r], [min(c, N-1), r], [c, max(0, r)], [c, min(r, N-1)]] # left, right, up, down
for each point. I could then do unzip these lists to get row and column coordinates for NP fancy indexing, e.g.
vals = test_arr[indices_r, indices_c]
I wonder if something that is faster is doable. I have experimented with np.newaxis
ii = np.arange(-1, 1+1) # Moore neighborhood with distance 1
indices_r, indices_c = np.meshgrid(ii, ii, indexing="ij")
indices_r = indices_r.ravel()[:, np.newaxis] # (9) -> (9, 1)
indices_c = indices_c.ravel()[:, np.newaxis]
points_r = points_r[np.newaxis, :] # (2) -> (1, 2
points_c = points_c[np.newaxis, :]
indices_r = np.add(indices_r, points_r)
indices_c = np.add(indices_c, points_c)
However, there I have the problem that A) some indices exceed the array (IndexError) and that B) the neighboring indices may overlap.
Does someone have a neat solution for this?
Edit
A specific example.
test_arr = np.zeros((10, 10), dtype=int)
test_arr[[0, 1, 4], [0, 0, 8]] = 1 # set some entries to one
indices_r, indices_c = np.nonzero(test_arr)
I want to find the neighboring cells of points denoted by (indices_r[0], indices_c[0])
without using a for loop. In addition, I want to check for various other flags.
# Test mask
test_mask = np.zeros((10, 10))
test_mask[[2, 4], [0, 8]] = 1
test_mask = test_mask.astype(bool)
More precisely, I know I could to something like
valid_neighs =[]
for r, c in zip(indices_r, indices_c):
range_r, range_c = np.arange(r-1, r+2), np.arange(c-1, c+2) # Moore neighborhood
# neighs_r, neighs_c = np.meshgrid(range_r, range_c, indexing="ij")
for rr, cc in zip(neighs_r, neighs_c):
# Check various flags
if (0 <= rr <= 10 and 0 <= cc <= 10
and mask[rr, cc] is True): # within lattice and mask is True
valid_neighs.append(rr, cc)
I'm looking for a way that eliminates both for loops. Is there something like that?