How can I extract a centered window from a numpy array?

Question:

Suppose I have the following numpy array:

>>> a = np.arange(0,21,1)
>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])

Now suppose that I want to pick a window of length N, where 2 < N <= a.shape[0], such that the window is "centered" around one of the elements of the array a. For example, if I want to center a window of length N = 5 around the element 10 in array a, then this window would be:

>>> idx = 10 # index of the array element 10
>>> N = 5 # window size
>>> a[idx - N//2:idx + N//2 + 1]
array([ 8,  9, 10, 11, 12])

This method generalizes well for windows that are not near the edges of the array, but I can’t make it work otherwise. For example, if I want to extract a window of length N = 7 around the element 2 in a, then what I get is:

>>> idx = 2
>>> N = 7
>>> a[idx - N//2:idx + N//2 + 1]
array([], dtype=int32)

However what I want is:

>>> a[0:7]
array([0, 1, 2, 3, 4, 5, 6])

How can I generalize this method for windows near the edges of a?

Asked By: mhdadk

||

Answers:

Try with:

idx = 2
start = min(idx - N//2, 0)
a[start:start + N]

Note that this is not centered at idx=2.

Answered By: Quang Hoang

Based on Quang Hoang’s answer, here is what worked:

import numpy as np

a = np.arange(0,21,1)
idx = 5 # desired element index
N = 7 # window length

if N % 2: # if window length is odd
    step = N // 2
else: # if window length is even
    step = int(N/2 - 1)

# make sure starting index is between 0 and a.shape[0] - N
start = min(max(idx-step,0),a.shape[0] - N)
window = a[start:start + N]
Answered By: mhdadk

Use take and wrap if a small array, more readable in one line:

>>>a.take(range(idx - N//2, idx + N//2 + 1), mode="wrap")
array([20,  0,  1,  2,  3,  4,  5])

If it is big, performance might be an issue, you can use a view, see:
Numpy subarrays and relative indexing.

Answered By: BorjaEst
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.