Under the hood, it computes the subscripted indices (indices along each dimensions) for the dimensions covered by the mask starting from the dimension it maps from, while selecting all elements from the un-indexed axes.
Case 1: 3D
data and 2D
mask
For example with b
of two dimensions, it maps onto two dimensions and hence with x[b]
, it maps starting from the first axis onward.
The subscripted indices are computed with np.where/np.nonzero
:
r,c = np.nonzero(b)
Thus, x[b]
translates to x[r, c, :]
, or simply x[r, c]
. So, then it uses advanced-indexing
to select elements off each axis axis from the pairs of indexing tuples
formed off r
and c
.
Case 2: 4D
data and 2D
mask
Now, let's increase the dimensionality of data array to 4D
, keeping the same 2D
mask, but index starting from the second axis onward, i.e. x[:, b]
.
Let's say we have
x = np.arange(60).reshape(2,2,3,5)
Get the subscripted indices and then use advanced-indexing
:
r,c = np.nonzero(b)
So, x[:, b]
should be same as x[:, r, c]
:
In [148]: x = np.arange(60).reshape(2, 2, 3, 5)
In [149]: b = np.array([[True, True, False], [False, True, True]])
In [150]: r,c = np.nonzero(b)
In [151]: np.allclose(x[:, b], x[:, r, c])
Out[151]: True
Case 3: 4D
data and 3D
mask
To go deeper, let's consider a 3D
mask array with 4D
data array and use all of the theory proposed earlier for verification:
In [144]: x = np.arange(60).reshape(2, 2, 3, 5)
...: b = np.random.rand(2, 3, 5) > 0.5
In [146]: r, c, p = np.nonzero(b)
In [147]: np.allclose(x[:, b], x[:, r, c, p])
Out[147]: True
As for the edit, x[[False, False, False, True]]
, you are indexing only along the first axis with a boolean array of length 5
, whereas the first axis of x
has a length smaller than that, hence reports an error on indexing.