Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Recipe: JAX vmap over a SpatialPatcher

Builds a (N, *patch_shape) batched array suitable for eqx.filter_vmap / jax.vmap. geopatcher does not depend on JAX — bring your own:

pip install jax equinox

The primitives this recipe uses:

PrimitiveRole
patcher.anchors(field)Indexable anchor list
patcher.patch_at(field, anchor)Per-anchor read
gp.stack_patches(patches)Stack to (N, H, W) for vmap

Materialise then stack

Patcher iteration is Python — not traced. Materialise to a list, then stack_patches to a (N, H, W) ndarray, then jnp.asarray to push to device.

batch shape: (16, 32, 32), dtype: float32

vmap a tiny model

eqx.filter_vmap over the batch axis runs the same model on every patch in parallel. The output preserves the (N, *) shape.

outputs shape: (16, 32, 32), mean: 13291.881

Stitching back

Pull the JAX outputs back to numpy, wrap each slice as a Patch, and feed patcher.merge. The patcher’s SpatialSum aggregation handles the assembly.

stitched shape: (128, 128)

Ragged geometries

stack_patches raises a clear ValueError when patches have different shapes (e.g. SpatialRadiusGraph, SpatialPolygonIntersection). For those, drop vmap and run the model one patch at a time — JAX’s pad → jit → vmap pattern is the right escape hatch.