Scenario
I have a 4D ndarray consisting of multiple 3D images/voxels with dimensions (voxels, dim1, dim2, dim3), let's say (12 voxels, 96 pixels, 96 pixels, 96 pixels). My goal is to sample a range of n slices from the middle of the volume of m voxels.
I have reviewed the Numpy documentation on (advanced) indexing, as well as this answer that explains broadcasting, and this answer that explains the insertion of a newaxis
by numpy, but I am still unable to understand the underlying behaviour in my scenario.
Problem
Initially, I attempted to achieve the above by indexing the array in one go using the following code:
import numpy as np
array = np.random.rand(12, 96, 96, 96)
n = 4
m_voxels = 6
samples_range = np.arange(0, m_voxels)
middle_slices = array.shape[1] // 2
middle_slices_range = np.arange(middle_slices - n // 2, middle_slices + n // 2)
samples_from_the_middle = array[samples_range, middle_slices_range, :, :]
Instead of obtaining an array of shape (6, 4, 96, 96), I encountered the following IndexError:
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (6,) (4,)
when I attempted to index the array explicitly or in two steps, it worked as expected:
explicit_indexing = array[0:6, 46:50, :, :]
temp = array[samples_range]
samples_from_the_middle = temp[:, middle_slices_range, :, :]
explicit_indexing.shape # output: (6, 4, 96, 96)
samples_from_the_middle.shape # output: (6, 4, 96, 96)
Alternatively, as mentioned in this answer, another approach would be:
samples_from_the_middle = array[samples_range[:, np.newaxis], middle_slices_range, :, :]
samples_from_the_middle.shape # output: (6, 4, 96, 96)
I have the following questions:
- Why does the
np.arange
approach fail to produce the expected result while the explicit indexing (with a colon) works correctly, even though we're practically indexing with the same range of integers? - Why does the addition of a
newaxis
to the first indexing 1D-array seem to resolve the issue?
Any insights would be greatly appreciated.