1

I have a function which takes a 3D numpy array (which we'll call a volume), and converts it into a list of 2D slices. I want the user to be able to specify the axis through which it is sliced. I am managing this with the code below, but the triple if statement doesn't seem like the most elegant way to do this. I would appreciate people's thoughts on if this could be achieved in a better way.

axis = 0 # Can be set to 0, 1, or 2 

volume = np.ones((100, 100, 100))

n_slices = volume.shape[axis]

slices = []

for i in range(n_slices):

    if axis == 0:
        my_slice = volume[i, :, :]
    elif axis == 1:
        my_slice = volume[:, i, :]
    elif axis == 2:
        my_slice = volume[:, :, i]

    slices.append(my_slice)
Mohamad Zeina
  • 404
  • 3
  • 20

3 Answers3

3

Simply use np.moveaxis -

slices_ar = np.moveaxis(volume,axis,0)

Best part is that it's a view into the input and hence virtually free on runtime. Let's verify the view-part -

In [83]: np.shares_memory(volume, np.moveaxis(volume,axis,0))
Out[83]: True

Alternatively, use np.rollaxis that does the same -

np.rollaxis(volume,axis,0)
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • 1
    Thanks, didn't think of this. Chosen as correct answer because it still works in my slightly more complicated scenario with no problems: some volumes have one channel, and some have more – Mohamad Zeina Sep 25 '19 at 20:09
1

I guess what you want is [numpy.split()]:(https://docs.scipy.org/doc/numpy/reference/generated/numpy.split.html)

axis = 0 # Can be set to 0, 1, or 2 
volume = np.ones((100, 100, 100))
n_slices = volume.shape[axis]

slices = np.split(volume, n_slices, axis)
Brandt
  • 5,058
  • 3
  • 28
  • 46
1

You could use

my_slice = volume[tuple(i if n == axis else slice(100) for n in range(3))]

so that

slices = [volume[tuple(i if n == axis else slice(100) for n in range(3))] for i in range(100)]
fuglede
  • 17,388
  • 2
  • 54
  • 99