NumPy mgrid: Dense Mesh Grids, Slice Steps, and Memory Tradeoffs

Quick answer: np.mgrid is an indexing object that creates dense coordinate arrays from slice notation. A normal integer step behaves like arange and excludes the stop value; a complex step such as 5j requests a number of evenly spaced points including the endpoint. Because mgrid materializes full coordinate planes, compare ogrid or sparse meshgrid when grid size makes memory important.

Python Pool infographic comparing NumPy mgrid dense grids ogrid sparse grids meshgrid and broadcasting memory
mgrid creates dense coordinate arrays from indexing slices; compare ogrid or sparse meshgrid when full coordinate planes would waste memory.

numpy.mgrid creates dense coordinate arrays from slice syntax. It is commonly described as mgrid(), but you use square brackets such as np.mgrid[0:3, 0:4] rather than a normal function call.

The official NumPy documentation covers numpy.mgrid, numpy.ogrid, and numpy.meshgrid().

Use mgrid when you want full row and column coordinate arrays. The result is dense, which means each output has the full grid shape. This is convenient for calculations, but it can use more memory than open-grid forms.

The slice syntax follows familiar start, stop, and step rules. A normal integer step behaves like arange() and stops before the endpoint. A complex step such as 5j asks NumPy for five evenly spaced points, including the endpoint.

For image-like arrays, matrix coordinates, distance maps, and surface calculations, mgrid can make the coordinate setup compact and readable.

For very large grids, compare it with ogrid. ogrid returns open coordinate arrays that broadcast together without storing every full coordinate plane.

Another common choice is meshgrid(), which builds coordinate arrays from existing one-dimensional coordinate inputs. Use mgrid when the coordinate ranges are naturally expressed as slices. Use meshgrid() when you already have coordinate arrays from another calculation.

Be deliberate about axis order. In many array workflows, the first coordinate corresponds to rows and the second coordinate corresponds to columns. Naming the outputs as rows and cols, or y and x, prevents confusion later.

Create A 1D Grid

A single slice creates one coordinate array.

import numpy as np

grid = np.mgrid[0:5]

print(grid)

This returns values from 0 through 4.

The endpoint is excluded because the slice uses a normal integer step.

This behavior is similar to np.arange(0, 5).

A one-dimensional grid is useful for checking syntax before moving to two axes.

It is also useful for quick index ranges where you want an array result immediately. For larger coordinate systems, the same slice idea extends cleanly to multiple axes. mgrid creates dense coordinate arrays, while NumPy ix_ Guide for Open Mesh Indexing creates an open mesh for selecting combinations of row and column indexes.

Create A 2D Dense Grid

Pass two slices to create row and column coordinate arrays.

import numpy as np

rows, cols = np.mgrid[0:3, 0:4]

print(rows)
print(cols)
print(rows.shape, cols.shape)

Both outputs have shape (3, 4).

The first output stores row coordinates across each column.

The second output stores column coordinates across each row.

Because both arrays have the same shape, you can combine them directly in element-wise formulas.

This is the main reason to choose dense grids: every coordinate array lines up cell by cell. That makes the later formula look almost the same as the mathematical expression you are trying to implement.

Python Pool infographic showing row and column ranges, slice notation, steps, and NumPy mgrid
Grid ranges: Row and column ranges, slice notation, steps, and NumPy mgrid.

Use Complex Step Counts

A complex step such as 5j means the number of points to generate.

import numpy as np

x, y = np.mgrid[0:1:5j, 0:1:3j]

print(x)
print(y)

Here, the first axis has five points and the second axis has three points.

With complex step counts, the endpoint is included.

This is useful when you need a fixed number of samples across a numeric interval.

Use this form for coordinate samples where endpoint inclusion matters.

The complex step notation is easy to miss because the letter j usually marks complex numbers in Python. In this slice position, NumPy uses it as a compact way to request a count of evenly spaced samples.

Compare mgrid And ogrid

mgrid creates dense arrays. ogrid creates open arrays that broadcast together.

import numpy as np

dense_rows, dense_cols = np.mgrid[0:3, 0:4]
open_rows, open_cols = np.ogrid[0:3, 0:4]

print(dense_rows.shape, dense_cols.shape)
print(open_rows.shape, open_cols.shape)

The dense arrays both have the full grid shape.

The open arrays have shapes that are smaller but still broadcast across the grid.

Use mgrid when full coordinate arrays make later code clearer.

Use ogrid when memory use matters and broadcasting is enough.

For small examples, both approaches are easy to inspect. For high-resolution surfaces, dense arrays can become large quickly, so checking shapes before a full calculation is a good habit.

Python Pool infographic mapping two ranges into dense coordinate grids with row and column axes
Dense mesh: Two ranges into dense coordinate grids with row and column axes.

Calculate Distances On A Grid

Coordinate arrays are often used in formulas.

import numpy as np

y, x = np.mgrid[-2:3, -2:3]

distance = np.sqrt(x**2 + y**2)

print(distance)

This calculates each cell distance from the center point.

The row and column coordinates are combined element by element.

The same pattern works for masks, kernels, surfaces, and spatial calculations.

Use clear names for axes so row-column order does not become confusing.

The same approach can create circular masks, radial weights, or simple coordinate-based filters. Since the coordinate arrays are ordinary NumPy arrays, every usual element-wise operation is available.

Build Coordinate Pairs

You can flatten coordinate arrays and stack them into coordinate pairs.

import numpy as np

rows, cols = np.mgrid[0:2, 0:3]

pairs = np.stack((rows.ravel(), cols.ravel()), axis=-1)

print(pairs)

This produces row-column pairs for every grid cell.

The pattern is useful when another tool expects coordinates as one pair per row.

In short, use np.mgrid[...] for dense coordinate arrays, use complex steps for fixed inclusive samples, and consider ogrid when broadcasting can avoid storing full grids.

Python Pool infographic comparing real step, complex sample count, endpoints, dtype, and grid shape
Step semantics: Real step, complex sample count, endpoints, dtype, and grid shape.

Read The Slice Shape

For two dimensions, mgrid returns one stacked array whose first axis identifies the coordinate dimension and whose remaining axes are the grid rows and columns. Naming the result carefully prevents confusing row coordinates with column coordinates.

import numpy as np

coords = np.mgrid[0:3, 10:14]
rows = coords[0]
cols = coords[1]
print(coords.shape)
print(rows)
print(cols)

Use A Complex Step For Exact Counts

The complex-step form is useful when the number of samples matters more than the step size. The imaginary part is not a complex coordinate here; its integer magnitude requests the number of points, including the stop endpoint.

import numpy as np

points = np.mgrid[-1:1:5j]
print(points)
print(len(points))
print(points[0], points[-1])
Python Pool infographic testing memory size, dimension order, empty ranges, dtype, and indexing
Grid checks: Memory size, dimension order, empty ranges, dtype, and indexing.

Compare Dense And Open Grids

mgrid stores every coordinate plane at full size. ogrid stores one non-singleton dimension per coordinate, and later NumPy operations broadcast those arrays when a full result is actually needed. This can reduce intermediate memory for separable calculations.

import numpy as np

full = np.mgrid[0:1000, 0:2000]
open_grid = np.ogrid[0:1000, 0:2000]
print(full.shape)
print(open_grid[0].shape, open_grid[1].shape)

distance = open_grid[0] ** 2 + open_grid[1] ** 2
print(distance.shape)

Use meshgrid When Inputs Already Exist

meshgrid is often clearer when x and y vectors come from another calculation or when indexing=’ij’ versus indexing=’xy’ must be explicit. sparse=True provides open-style arrays without using mgrid slice notation.

import numpy as np

x = np.linspace(-1, 1, 4)
y = np.linspace(0, 2, 3)
X, Y = np.meshgrid(x, y, indexing="ij", sparse=True)
field = X ** 2 + Y ** 2
print(X.shape, Y.shape)
print(field.shape)

NumPy documents mgrid as a dense multi-dimensional mesh-grid and explains its integer and complex slice steps. The ogrid reference covers open grids, while meshgrid documents indexing and sparse output. Related references include ogrid, arange, and reshaping grids.

For related coordinate-grid choices, compare ogrid, arange(), and reshaping arrays before materializing a large dense grid.

Frequently Asked Questions

What is NumPy mgrid?

np.mgrid is an indexing object that creates dense multi-dimensional mesh grids from slice notation, with each coordinate array sharing the full grid shape.

Does mgrid include the stop value?

A normal integer step excludes the stop value, while a complex step such as 5j requests a number of evenly spaced points including the endpoint.

What is the difference between mgrid and ogrid?

mgrid returns dense coordinate arrays, while ogrid returns open arrays that broadcast together and usually use less memory.

When should I use meshgrid instead of mgrid?

Use meshgrid when you already have one-dimensional coordinate vectors or need explicit indexing and sparse options; use mgrid when slice notation is the clearest input.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted