Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python NumPy - angled slice of 3D array

Working in NumPy, I understand how to slice 2D arrays from a 3D array using this article.

Depending on the axis I'd want to slice in:

array = [[[0  1  2]
          [3  4  5]
          [6  7  8]]

         [[9  10 11]
          [12 13 14]
          [15 16 17]]

         [[18 19 20]
          [21 22 23]
          [24 25 26]]]

Slicing would give me:

i_slice = array[0]

    [[0  1  2]
     [3  4  5]
     [6  7  8]]

j_slice = array[:, 0]

    [[0  1  2]
     [9  10 11]
     [18 19 20]]

k_slice = array[:, :, 0]

    [[0  3  6]
     [9  12 15]
     [18 21 24]]

But is it possible to slice at a 45 degree angle? such as:

j_slice_down = array[slice going down starting from index 0]

    [[0  1  2]
     [12 13 14]
     [24 25 26]]

I was able to achieve this in all 3 axis's going up or down, and even wrapping all the way around... in the dark list days with many for loops... but I'm sure there must be a better way in NumPy.

Update, chosen answer:

I chose hpaulj's answer creating two coordinate arrays with np.arrange. With a little work, I was able to make it fit my needs of returning a slice at any angle, on any axis, asymmetric dimension of 3D array, and at any position, including wrapping all the way around so that it is the same dimension as the axis.

My method using np.arrange

Two np.arrange arrays were made for an x and y.

Different methods such as np.roll, incrementing, np.hstack and np.concatenate were done on the np.arrange array x axis array. y = y[::-1] for the alternate angle.

if axis is 'z': #i
    slice_notation = np.index_exp[x, y, :] 

elif axis is 'y': #k
    slice_notation = np.index_exp[x, :, y]

else: #j 
    slice_notation = np.index_exp[:, x, y]

Creates the slice expression, then I use the slice_notation to perform my needed operations in place.

The other proposed methods: np.diagonal and np.eye may be more suitable for others though as they may have different requirements than me.

like image 736
Enger Bewza Avatar asked Feb 18 '19 07:02

Enger Bewza


2 Answers

In [145]: arr[np.arange(3), np.arange(3),:]
Out[145]: 
array([[ 0,  1,  2],
       [12, 13, 14],
       [24, 25, 26]])
like image 77
hpaulj Avatar answered Sep 29 '22 03:09

hpaulj


You can try with np.diagonal:

arr = np.array([[[0  ,1  ,2],
          [3  ,4  ,5],
          [6  ,7  ,8]],
         [[9  ,10 ,11],
          [12 ,13 ,14],
          [15 ,16 ,17]],
         [[18 ,19 ,20],
          [21 ,22 ,23],
          [24 ,25 ,26]]])

np.diagonal(arr).T
array([[ 0,  1,  2],
       [12, 13, 14],
       [24, 25, 26]])
like image 24
Chris Avatar answered Sep 29 '22 03:09

Chris