# [SOLVED] how does the np.index_exp[] work in the 3D voxel / volumetric plot with rgb colors example

## Issue

But I don’t understand how the indexing works in the example. Can any one help me to understand. Thanks

``````> def midpoints(x):
> sl = ()
> for i in range(x.ndim):
>>    x = (x[sl + np.index_exp[:-1]] + x[sl + np.index_exp[1:]])
>>    sl += np.index_exp[:]
>>    print(np.index_exp[:-1])
>>    print(x[np.index_exp[:-1]])
``````
``````I know the "index_exp[:-1]" returns (slice(None,None,-1),) and "x[index_exp[:-1]]" will give result like this:
[[[0 0 0],
[0 0 0],
[0 0 0]],
[[1 1 1],
[1 1 1],
[1 1 1]]]

But I don't understand how the ```x[index_exp[:-1]]``` in the for loop only shows:
[[[1 1 1],
[1 1 1],
[1 1 1]]]
``````

## Solution

In the example, `x`, is one of the (17,17,17) arrays produced by

``````In : r, g, b = np.indices((17, 17, 17)) / 16.0
...: rc = midpoints(r)
...: gc = midpoints(g)
...: bc = midpoints(b)
``````

`indices` is like `meshgrid` and `mgrid`, creating grid arrays.

I haven’t used `np.index_exp`, but I see it’s the same as `np.s_`, except it always returns a tuple

``````In : x = r.copy()
In : ()+np.index_exp[:-1]    # so this tuple can joined with sl
Out: (slice(None, -1, None),)
In : x[()+np.index_exp[:-1]].shape
Out: (16, 17, 17)
In : x[:-1].shape
Out: (16, 17, 17)
``````

so

``````x = (x[sl + np.index_exp[:-1]] + x[sl + np.index_exp[1:]])/2.0
``````

for the initial `sl`, this is

``````x = (x[:-1] + x[1:])/2.0
``````

`x[1:]-x[:-1]` is widely used to take the difference between adjacent elements, `np.diff`. Here it just acts on the first dimension (of 3). So this is just the mean of adjacent points. Note both `x[:-1]` and `x[1:]` are (16,17,17) arrays.

The next bit just adds a `[:]` slice to `sl`:

``````In : sl += np.index_exp[:]
In : sl
Out: (slice(None, None, None),)
In : sl + np.index_exp[:-1]
Out: (slice(None, None, None), slice(None, -1, None))
``````

So this is doing

`````` x[:, :-1]     # which should be a (17,16,17) array
``````

and the next iteration `x[:,:, :-1] # (17,17,16)`

This `r` varies only in the first dimension, so can compare its values with the `midpoints` with:

``````In : r1 = midpoints(r)
In : r[:5,0,0]
Out: array([0.    , 0.0625, 0.125 , 0.1875, 0.25  ])
In : r1[:4,0,0]
Out: array([0.03125, 0.09375, 0.15625, 0.21875])
``````

So the use `index_exp` just allows them to write the `(x[:-1]+x[1:])/2` averaging in a general way that applies to all 3 dimensions the `r`, `g`.`b` arraus/