1

I have a 4-dimensional array with size (d1,d2,d3,d4), and a list of indices with k entries. Each element of the indices list has 3 elements. The first is the index for the 1st dimension of the array. The second and third correspond to the start of slices for the 3rd and 4th dimension, where the slice length is a fixed number n. From the second dimension of the array I always want all elements. In the end I want to have a new array with size (k,d3,n,n). For performance reasons I want to do this without a for loop, and if possible without data-copying. The following solution works, but uses a for loop and copies the data:

d1,d2,d3,d4 = 3,4,10,10
data = np.arange(d1*d2*d3*d4).reshape((d1,d2,d3,d4))
idcs_all = [[0,4,6],
        [2,2,5]]
n = 3
k=len(idcs_all)
sub = np.zeros((k,d2,n,n))

for i, idcs in enumerate(idcs_all):
    sub[i] = data[idcs[0],:, idcs[1]:idcs[1]+n, idcs[2]:idcs[2]+n]

Is there a way to do the same with fancy indexing?

hpaulj
  • 221,503
  • 14
  • 230
  • 353
Sip
  • 150
  • 1
  • 8

1 Answers1

1

We can leverage np.lib.stride_tricks.as_strided based scikit-image's view_as_windows to get sliding windows. More info on use of as_strided based view_as_windows. Then, indexing into those windows with advanced-indexing using those indices from idcs_all solves it for us!

from skimage.util import view_as_windows

w = view_as_windows(data,(1,1,n,n))[...,0,0,:,:]
idcs_all = np.asarray(idcs_all)
sub = w[idcs_all[:,0],:,idcs_all[:,1],idcs_all[:,2]]
Divakar
  • 218,885
  • 19
  • 262
  • 358