NumPy·Lesson 23·9 min·0/3 exercises

Coordinate grids

meshgrid, mgrid, ogrid — how you compute a function of position without a loop.

np.meshgridnp.mgridnp.ogridnp.indicesnp.hypotsparse grids

Watch it happen

Play it through, or step back and forth yourself.

xx (column number)
0
1
2
3
0
1
2
3
0
1
2
3
shape (3, 4)
yy (row number)
0
0
0
0
1
1
1
1
2
2
2
2
shape (3, 4)

You want to evaluate something at every position of a grid — a distance from the centre, a colour ramp, a function of two variables. Broadcasting can do it, but first you need arrays holding the x and y of every cell.

The idea

Some values depend on where they are rather than on other data: a distance from a centre, a colour ramp, a height field, a decision boundary drawn across a plane. For those you need arrays holding the coordinates themselves.

xx, yy = np.meshgrid(np.arange(4), np.arange(3))
xx     # [[0 1 2 3], [0 1 2 3], [0 1 2 3]]   — column number
yy     # [[0 0 0 0], [1 1 1 1], [2 2 2 2]]   — row number

Two arrays of the same shape: one holds every cell's x, the other every cell's y. After that, any function of position is ordinary vectorised arithmetic — no loops:

xx + yy
np.sqrt(xx**2 + yy**2)
np.sin(xx / 3) * np.cos(yy / 3)

Three spellings, and an ordering trap

xx, yy = np.meshgrid(x, y)      # columns first
yy, xx = np.mgrid[0:3, 0:4]     # ROWS first — note the swap
yy, xx = np.ogrid[0:3, 0:4]     # sparse: shapes (3,1) and (1,4)

meshgrid takes arrays and returns x-then-y. mgrid takes slice syntax and returns them in axis order, which for a 2-D grid means rows first. Getting that backwards gives you a transposed result that looks almost right, so it's worth reading the line carefully.

ogrid is the efficient one. Rather than two full grids it returns shapes (3, 1) and (1, 4) and lets broadcasting do the expansion — same answer, a fraction of the memory. For a 4000×4000 grid that's the difference between 256MB of coordinates and 64KB. meshgrid has a sparse=True that does the same thing.

Hand-drawn notes showing two one-dimensional ranges expanded by meshgrid into two full grids of coordinates, one holding the x value at every position and the other the y value.

Distance fields

The pattern you'll use most:

yy, xx = np.mgrid[0:H, 0:W]
d = np.hypot(xx - cx, yy - cy)     # distance from (cx, cy) at every pixel

mask = d < 40                      # a circular mask
falloff = np.clip(1 - d / 40, 0, 1)   # a soft radial gradient

np.hypot(a, b) is sqrt(a**2 + b**2) without the intermediate overflow. Circular crops, vignettes, spotlight effects and radial blurs all start here.

Hand-drawn notes showing ogrid storing only a column and a row where meshgrid stores two full grids, with broadcasting producing the same result from far less memory.

You have already used this

The sunset in the first capstone was built exactly this way — a coordinate grid, a vertical ramp for the sky, a radial falloff for the sun, a sine wave for the hills, and np.where to paint the ground in. Go back and read that setup code now; it should look completely ordinary.

np.indices((3, 4)) is a related shortcut that stacks the same coordinate arrays into one array of shape (2, 3, 4).

Practice

Write it yourself. The answer is there when you want it.

Putting the kettle on…

Starting up…

Write it yourself

not graded

Build xx, yy with np.meshgrid over arange(4) and arange(3), and print both grids and their sum. Do the same with np.ogrid, printing the shapes so you can see how much less it stores for the same answer. Finish with a 9×9 np.mgrid and a circle: distance from the centre with np.hypot, under a radius of 3, as ints.

Write something and press Run — the output appears here.

Your turn

3 exercises. Write the code yourself, then press Check — a nudge and the answer are there if you want them.

Build coordinate grids for a 3 x 4 area with np.meshgrid and return xx + yy.

your answer

Use np.mgrid[0:3, 0:4] and return just the row-number grid.

your answer

On a 9 x 9 grid, return an integer array that is 1 where the distance from (4, 4) is less than 3, and 0 elsewhere.

your answer