## Issue

I am reading the example: https://matplotlib.org/stable/gallery/mplot3d/voxels_rgb.html#sphx-glr-gallery-mplot3d-voxels-rgb-py about creating a 3d sphere.

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 [208]: 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 [225]: x = r.copy()
In [226]: ()+np.index_exp[:-1] # so this tuple can joined with sl
Out[226]: (slice(None, -1, None),)
In [227]: x[()+np.index_exp[:-1]].shape
Out[227]: (16, 17, 17)
In [228]: x[:-1].shape
Out[228]: (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 [230]: sl += np.index_exp[:]
In [231]: sl
Out[231]: (slice(None, None, None),)
In [232]: sl + np.index_exp[:-1]
Out[232]: (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 [249]: r1 = midpoints(r)
In [250]: r[:5,0,0]
Out[250]: array([0. , 0.0625, 0.125 , 0.1875, 0.25 ])
In [251]: r1[:4,0,0]
Out[251]: 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/

Answered By – hpaulj

Answer Checked By – Clifford M. (BugsFixing Volunteer)