0

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?

LionCereals
  • 171
  • 1
  • 10

0 Answers0