Question

I am writing a piece of code to print the nearest neighbors for the elements of a matrix. I get an

"invalid index" error

when I try to print the list of the neighbours (last line). Can you spot why?

Here's the code:

neighbours = ndarray((ran_x-2, ran_y-2,8),int)
for i in range(0, ran_x):
    for j in range(0, ran_y):
        if 1 < i < ran_x-1:
           if 1 < j < ran_y-1:
              neighbours = ([matrix[i-1,j-1],matrix[i-1,j],matrix[i-1,j+1],matrix[i,j-1],matrix[i,j+1],matrix[i+1,j-1],matrix[i+1,j],matrix[i+1,j+1]])
neighbours = np.array(neighbours)
for l in range(1, ran_x-1):
    for m in range(1, ran_y-1):                
        print neighbours[l,m]
Was it helpful?

Solution 3

The problem is you continuously reassign neighbours to a 1D array with length 8. Instead you should assign the neighbour data to a slice of the array you had already created:

for i in range(1, ran_x-1):
    for j in range(1, ran_y-1):
        neighbours[i-1,j-1,:] = [matrix[i-1,j-1],matrix[i-1,j],matrix[i-1,j+1],matrix[i,j-1],matrix[i,j+1],matrix[i+1,j-1],matrix[i+1,j],matrix[i+1,j+1]]

Note that I changed the ranges so you don't need the if statements. Your code would be faster and (arguably) neater as the following:

neighbours = np.empty((ran_x-2, ran_y-2, 8), int)

# bool array to extract outer ring from a 3x3 array:
b = np.array([[1,1,1],[1,0,1],[1,1,1]], bool)

for i in range(ran_x-2):
    for j in range(ran_y-2):
        neighbours[i,j,:] = matrix[i:i+3, j:j+3][b]

Of course it would be faster still to immediately print the neighbours without storing them at all, if that's all you need.

OTHER TIPS

Look at the size of your array, it's a (ran_x - 2) * (ran_y - 2) elements array:

neighbours = ndarray((ran_x-2, ran_y-2,8),int)

And you try to access the elements at index ran_x-1 and ran_y-1 which are out of bound.

sliding window stride_tricks is great for this (https://stackoverflow.com/a/11000193/541038)

import numpy as np
from numpy.lib.stride_tricks import as_strided

def sliding_window(arr, window_size):
    """ Construct a sliding window view of the array"""
    arr = np.asarray(arr)
    window_size = int(window_size)
    if arr.ndim != 2:
        raise ValueError("need 2-D input")
    if not (window_size > 0):
        raise ValueError("need a positive window size")
    shape = (arr.shape[0] - window_size + 1,
             arr.shape[1] - window_size + 1,
             window_size, window_size)
    if shape[0] <= 0:
        shape = (1, shape[1], arr.shape[0], shape[3])
    if shape[1] <= 0:
        shape = (shape[0], 1, shape[2], arr.shape[1])
    strides = (arr.shape[1]*arr.itemsize, arr.itemsize,
               arr.shape[1]*arr.itemsize, arr.itemsize)
    return as_strided(arr, shape=shape, strides=strides)

def cell_neighbors(arr, i, j, d):
    """Return d-th neighbors of cell (i, j)"""
    w = sliding_window(arr, 2*d+1)

    ix = np.clip(i - d, 0, w.shape[0]-1)
    jx = np.clip(j - d, 0, w.shape[1]-1)

    i0 = max(0, i - d - ix)
    j0 = max(0, j - d - jx)
    i1 = w.shape[2] - max(0, d - i + ix)
    j1 = w.shape[3] - max(0, d - j + jx)

    return w[ix, jx][i0:i1,j0:j1].ravel()

x = np.arange(8*8).reshape(8, 8)
print x

for d in [1, 2]:
    for p in [(0,0), (0,1), (6,6), (8,8)]:
        print "-- d=%d, %r" % (d, p)
        print cell_neighbors(x, p[0], p[1], d=d)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top