Skip to content

S2

S2 spherical cells, fixed-level and adaptive covers, and hierarchical cell sets.

Related: Grid-generic API

Types

S2Cell

Accepted call forms
S2Cell(value: S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str, /) -> S2Cell
S2Cell(value: Point, /, *, level: int | integer[Any]) -> S2Cell
S2Cell(value: FloatScalar | ScalarFloatArray, /, lat: FloatScalar | ScalarFloatArray, *, level: int | integer[Any]) -> S2Cell

One S2 cell: a level-addressed quadrilateral tile on the sphere.

Wraps the 64-bit cell id with typed accessors (cell.level, cell.token, cell.polygon, cell.center) and hierarchy moves (parent/children/neighbors). Convert via S2Cell(...), and back with int(cell).

One S2 cell from an id, token, lon/lat pair, or point geometry.

Parameters:

Name Type Description Default
value S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Point | (FloatScalar | ScalarFloatArray)

An existing cell, id, token, longitude of a lon, lat pair, or a point geometry.

required
level int | integer[Any]

S2 level (0-30); required for coordinate construction.

varies by call form
lat FloatScalar | ScalarFloatArray

Latitude when value is a scalar longitude.

varies by call form

Returns:

Type Description
S2Cell

Raises:

Type Description
ParseError

If value is not a valid S2 cell id or token.

GeometryError

If level is out of range.

InvalidGeometryError

If a scalar coordinate is non-finite or out of range.

level property

level: int

S2 level of this cell (0-30).

Returns:

Type Description
int

children

children(level: int | None = None) -> CellArray[S2Cell]

Child cells at a finer level.

Parameters:

Name Type Description Default
level int

Target level; must not be coarser than this cell's. Defaults to one finer than this cell's level; a maximum-depth cell has no children and yields an empty CellArray.

None

Returns:

Type Description
CellArray of S2Cell

The descendant cells in the grid's public identity order.

Raises:

Type Description
GeometryError

If the target depth is invalid for this cell.

Examples:

>>> import gometry as gm
>>> cell = gm.s2_cover(gm.Point(-122.4194, 37.7749, crs=4326), level=12)[0]
>>> assert cell is not None
>>> len(cell.children(13))
4

children_count

children_count(level: int | None = None) -> int

Number of descendant cells at a finer level, counted closed-form without materializing them.

Parameters:

Name Type Description Default
level int

Target level; must not be coarser than this cell's. Defaults to one finer than this cell's level; a maximum-depth cell has no children and returns 0.

None

Returns:

Type Description
int

The exact descendant count.

Raises:

Type Description
GeometryError

If the target depth is coarser than this cell's, or invalid.

Examples:

>>> import gometry as gm
>>> cell = gm.s2_cover(gm.Point(-122.4194, 37.7749, crs=4326), level=12)[0]
>>> assert cell is not None
>>> cell.children_count(13)
4

parent

parent(level: int | None = None) -> S2Cell

Parent cell at a coarser level.

Parameters:

Name Type Description Default
level int

Target level; must not be finer than this cell's. Defaults to one coarser than this cell's level.

None

Returns:

Type Description
S2Cell

The ancestor cell.

Raises:

Type Description
GeometryError

If the target depth is invalid for this cell.

Examples:

>>> import gometry as gm
>>> cell = gm.s2_cover(gm.Point(-122.4194, 37.7749, crs=4326), level=12)[0]
>>> assert cell is not None
>>> cell.parent(10).token
'808581'

Functions

s2_bounding_cell

s2_bounding_cell(value: Geometry | GeometryArray[Geometry | None] | Iterable[float]) -> S2Cell

Return the deepest S2 cell that provably contains a geometry's lon/lat bounding box.

Sibling-consistent with geohash_bounding_cell / tile_bounding_cell / h3_bounding_cell: non-point inputs collapse to their lon/lat envelope, then the deepest cell that can be proven to cover that rectangle is returned. Near cell boundaries the result may be one level coarser than the theoretical deepest (always containing). A single point yields its exact level-30 leaf; a multipoint uses its bounding box (same path as any multi-vertex region — not a leaf-LCA of the vertices alone). Regions that span multiple cube faces have no single containing cell and raise.

Parameters:

Name Type Description Default
value Geometry, GeometryArray, or sequence of float

A geometry/array (non-WGS84 frames reproject), or a bare lon/lat (minx, miny, maxx, maxy) bounds.

required

Returns:

Type Description
S2Cell

The deepest cell that provably contains the geometry's bounding box; near boundaries may be coarser than theoretical deepest (always containing).

Raises:

Type Description
InvalidGeometryError

If the geometry is empty or coordinates leave the lon/lat domain.

GeometryError

If no single S2 cell contains the bounds, or bare bounds are not ordered min <= max.

Examples:

>>> import gometry as gm
>>> berlin = gm.box(13.3, 52.4, 13.5, 52.6, crs=4326)
>>> gm.s2_bounding_cell(berlin).level
8

s2_cells

Accepted call forms
s2_cells(values: GeometryArray[Point] | Iterable[Point] | (Sequence[Sequence[float]] | ndarray[tuple[int, int], dtype[floating[Any] | signedinteger[Any] | unsignedinteger[Any] | bool_]]) | FloatInput, lat: FloatInput | None = None, *, level: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer) -> CellArray[S2Cell]
s2_cells(values: GeometryArray[Point | None] | Iterable[Point | None], lat: None = None, *, level: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer) -> CellArray[S2Cell | None]

Build S2 cells from points, coordinate rows, or parallel lon/lat columns.

Parameters:

Name Type Description Default
values GeometryArray of Point, iterable of Point or None, coordinate matrix, or float

Point geometries (None makes a missing cell), a coordinate matrix with at least two columns, or WGS84 longitudes. Iterable points must share one CRS and epoch; projected point inputs are reprojected to WGS84. Coordinate matrices use only X and Y, ignoring extra ordinates.

required
lat float or sequence of float

WGS84 latitude per row when values supplies longitudes. Coordinate columns broadcast numpy-style; at least one must be a sequence.

None
level int or sequence of int

S2 cell level (0-30; finer at higher values). A scalar broadcasts to every row; an array supplies one level per row.

required

Returns:

Type Description
CellArray of S2Cell

One cell per input coordinate.

Raises:

Type Description
GeometryError

If level is out of range or every argument is scalar.

InvalidGeometryError

If a coordinate is non-finite or columns differ in length.

See Also

S2Cell : Build a single cell. s2_cover : Cover a geometry with S2 cells.

Examples:

>>> import gometry as gm
>>> len(gm.s2_cells([21.0, 22.0], [52.0, 53.0], level=10))
2

s2_cover

Accepted call forms
s2_cover(geom: GeometryArray[Geometry] | Iterable[Geometry], level: int | None = None, *, target_cells: int = 8, min_level: int | None = None, max_level: int | None = None, level_mod: Literal[1, 2, 3] = 1, cell_rule: Literal['center', 'within', 'overlap', 'bbox'] = 'overlap', max_cells: int | None = 1000000) -> Groups[CellArray[S2Cell]]
s2_cover(geom: GeometryArray[Geometry | None] | Iterable[Geometry | None], level: int | None = None, *, target_cells: int = 8, min_level: int | None = None, max_level: int | None = None, level_mod: Literal[1, 2, 3] = 1, cell_rule: Literal['center', 'within', 'overlap', 'bbox'] = 'overlap', max_cells: int | None = 1000000) -> Groups[CellArray[S2Cell] | None]
s2_cover(geom: Geometry, level: int | None = None, *, target_cells: int = 8, min_level: int | None = None, max_level: int | None = None, level_mod: Literal[1, 2, 3] = 1, cell_rule: Literal['center', 'within', 'overlap', 'bbox'] = 'overlap', max_cells: int | None = 1000000) -> CellArray[S2Cell]

Cover a geometry with fixed-level or adaptively refined S2 cells.

Omit level to adapt refinement to target_cells and the optional level range. Supplying level fixes the output depth; non-default adaptive controls cannot be combined with it. Keep the source geometry separately and use the free gm.* predicates for exact geometry questions.

Parameters:

Name Type Description Default
geom Geometry, GeometryArray, or iterable of Geometry or None

Geometry to cover (WGS84 lon/lat or projected). An array or iterable returns one group per input row; None produces a missing group and a present empty geometry produces an empty group.

required
level int

Fixed S2 cell level (0-30; finer at higher values). The level is never coarsened to fit the output cap. Omit it for adaptive refinement.

None
target_cells int

Approximate adaptive refinement target; the minimum admissible cover can exceed this value.

8
min_level int or None

Coarsest adaptive S2 level allowed; omission uses level 0.

None
max_level int or None

Finest adaptive S2 level allowed; omission uses level 30.

None
level_mod (1, 2, 3)

Restrict adaptive output levels to increments from min_level.

1
cell_rule ('within', 'center', 'overlap', 'bbox')

Which cells to materialize, strictest to loosest. 'within': only cells entirely inside — cells the area fully owns. 'center': cells whose center is inside — unique assignment, balanced point binning. 'overlap': every cell touching the geometry — a complete-coverage superset, the safe default for candidate keys. 'bbox': every cell meeting the geometry's envelope, one window per part and split at the antimeridian — loosest and fastest. The rule never affects the exact predicates.

'within'
max_cells int or None

Hard cap on returned cells, applied cumulatively across array groups. In fixed-level mode an insufficient cap raises; adaptive mode may coarsen only within its requested level range. Pass None for an unlimited cover.

1000000

Returns:

Type Description
CellArray or Groups of CellArray

A scalar returns its coverage; an array returns one cell group per row.

Raises:

Type Description
GeometryError

If the geometry, level, or a coverage parameter is invalid, if fixed and non-default adaptive controls are combined, or if the cover exceeds max_cells.

InvalidGeometryError

If a scalar geometry is empty or coordinates leave the lon/lat domain.

See Also

s2_cells : Build S2 cells from lon/lat columns. s2_cover : Cover with fixed or adaptive levels.

Examples:

>>> import gometry as gm
>>> p = gm.Point(-122.4194, 37.7749, crs=4326)
>>> cov = gm.s2_cover(p, level=12)
>>> cell = cov[0]
>>> assert cell is not None
>>> (len(cov), cell.token)
(1, '8085809')

s2_difference

s2_difference(left: S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None], right: S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None]) -> CellArray[S2Cell]

Hierarchy-aware difference of two S2 cell sets.

Cells of left partially covered by right split into children until the remainder is exact; the result is normalized in the grid's public identity order.

Parameters:

Name Type Description Default
left S2Cell, int, str, or iterable of those with missing values skipped

The two cell sets (any mix of cell objects, ids, or tokens).

required
right S2Cell, int, str, or iterable of those with missing values skipped

The two cell sets (any mix of cell objects, ids, or tokens).

required

Returns:

Type Description
CellArray of S2Cell

Raises:

Type Description
ParseError

If an id or token is not a valid S2 cell.

Examples:

>>> import gometry as gm
>>> p = gm.Point(-122.4194, 37.7749, crs=4326)
>>> cells = [cell for cell in gm.s2_cover(p, level=12) if cell is not None]
>>> len(gm.s2_difference(cells, []))
1

s2_intersection

s2_intersection(left: S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None], right: S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None]) -> CellArray[S2Cell]

Hierarchy-aware intersection of two S2 cell sets.

A cell survives where the two sets overlap; ancestor/descendant overlap keeps the finer cell.

Parameters:

Name Type Description Default
left S2Cell, int, str, or iterable of those with missing values skipped

The two cell sets (any mix of cell objects, ids, or tokens).

required
right S2Cell, int, str, or iterable of those with missing values skipped

The two cell sets (any mix of cell objects, ids, or tokens).

required

Returns:

Type Description
CellArray of S2Cell

Raises:

Type Description
ParseError

If an id or token is not a valid S2 cell.

Examples:

>>> import gometry as gm
>>> p = gm.Point(-122.4194, 37.7749, crs=4326)
>>> cells = [cell for cell in gm.s2_cover(p, level=12) if cell is not None]
>>> len(gm.s2_intersection(cells, cells))
1

s2_union

s2_union(left: S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None], right: S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[S2Cell | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None]) -> CellArray[S2Cell]

Hierarchy-aware union of two S2 cell sets.

Returns the normalized cell union in the grid's public identity order: contained cells are absorbed by their ancestors and complete sibling groups are merged into parents.

Parameters:

Name Type Description Default
left S2Cell, int, str, or iterable of those with missing values skipped

A single cell identity or a collection on either side (any accepted mix of cell objects and identity values for this grid).

required
right S2Cell, int, str, or iterable of those with missing values skipped

A single cell identity or a collection on either side (any accepted mix of cell objects and identity values for this grid).

required

Returns:

Type Description
CellArray of S2Cell

Raises:

Type Description
ParseError

If an id or token is not a valid S2 cell.

Examples:

>>> import gometry as gm
>>> p = gm.Point(-122.4194, 37.7749, crs=4326)
>>> cells = [cell for cell in gm.s2_cover(p, level=12) if cell is not None]
>>> len(gm.s2_union(cells, cells))
1