gedih3.egi.spatial#

EGI (EASE Grid Index) Spatial Module

This module provides spatial operations for EGI indices including: - Coordinate extraction from hashes - Geometry generation (points and polygons) - Neighbor finding (pixel ring) - Child pixel enumeration - Area of Interest (AOI) tile generation

Functions#

check_crs_limits(→ Tuple[Union[float, ...)

Clamp coordinates to EPSG:6933 valid bounds.

pixel_coordinate(→ Union[Tuple[float, float], ...)

Get the coordinate of an EGI pixel.

pixel_coordinates(...)

Get coordinates for multiple EGI pixels (vectorized).

pixel_shape(→ shapely.geometry.Polygon)

Get the bounding polygon of an EGI pixel.

pixel_ring(→ List[numpy.uint64])

Get the 8 neighboring pixels (ring) around an EGI pixel.

aoi_tiles(→ geopandas.GeoDataFrame)

Generate outer tiles (level 12) covering an area of interest.

to_geodataframe(→ geopandas.GeoDataFrame)

Convert EGI hashes to a GeoDataFrame.

egi_h3_intersection(→ dict)

Map EGI tiles to intersecting H3 partition cells using spatial index.

Module Contents#

gedih3.egi.spatial.check_crs_limits(x: float | numpy.typing.NDArray[numpy.floating], y: float | numpy.typing.NDArray[numpy.floating]) Tuple[float | numpy.typing.NDArray[numpy.floating], float | numpy.typing.NDArray[numpy.floating]][source]#

Clamp coordinates to EPSG:6933 valid bounds.

Parameters:
xfloat or array

X coordinate(s) in EPSG:6933

yfloat or array

Y coordinate(s) in EPSG:6933

Returns:
tuple

(x, y) clamped to valid bounds

gedih3.egi.spatial.pixel_coordinate(uint_hash: numpy.uint64, center: bool = True, return_point: bool = False) Tuple[float, float] | shapely.geometry.Point[source]#

Get the coordinate of an EGI pixel.

Parameters:
uint_hashuint64

EGI hash value

centerbool

If True, return pixel center; if False, return lower-left corner

return_pointbool

If True, return a Shapely Point; if False, return (x, y) tuple

Returns:
tuple or Point

(x, y) coordinates in EPSG:6933, or Shapely Point

Examples

>>> x, y = pixel_coordinate(hash_val)
>>> point = pixel_coordinate(hash_val, return_point=True)
gedih3.egi.spatial.pixel_coordinates(uint_hash: numpy.typing.NDArray[numpy.uint64], center: bool = True) Tuple[numpy.typing.NDArray[numpy.floating], numpy.typing.NDArray[numpy.floating]][source]#

Get coordinates for multiple EGI pixels (vectorized).

Parameters:
uint_hasharray of uint64

EGI hash values

centerbool

If True, return pixel centers; if False, return lower-left corners

Returns:
tuple

(x_array, y_array) coordinates in EPSG:6933

gedih3.egi.spatial.pixel_shape(uint_hash: numpy.uint64) shapely.geometry.Polygon[source]#

Get the bounding polygon of an EGI pixel.

Parameters:
uint_hashuint64

EGI hash value

Returns:
Polygon

Shapely polygon representing the pixel bounds

Examples

>>> geom = pixel_shape(hash_val)
>>> area_m2 = geom.area
gedih3.egi.spatial.pixel_ring(uint_hash: numpy.uint64, include_input: bool = False) List[numpy.uint64][source]#

Get the 8 neighboring pixels (ring) around an EGI pixel.

Parameters:
uint_hashuint64

EGI hash value (center pixel)

include_inputbool

If True, include the input pixel in the result

Returns:
list of uint64

EGI hashes of neighboring pixels (up to 8)

Notes

Pixels at the edge of the projection bounds will have fewer than 8 neighbors. The function correctly handles tile boundary crossings.

gedih3.egi.spatial.aoi_tiles(region: geopandas.GeoDataFrame | None = None) geopandas.GeoDataFrame[source]#

Generate outer tiles (level 12) covering an area of interest.

Parameters:
regionGeoDataFrame, optional

Area of interest. If None, returns all global tiles.

Returns:
GeoDataFrame

Tiles indexed by EGI level-12 hash with polygon geometries

Raises:
ValueError

If region has no CRS defined

Examples

>>> # Get tiles for a specific region
>>> region = gpd.read_file("study_area.shp")
>>> tiles = aoi_tiles(region)
>>>
>>> # Get all global tiles
>>> all_tiles = aoi_tiles()
gedih3.egi.spatial.to_geodataframe(uint_hash_iter: List[numpy.uint64] | numpy.typing.NDArray[numpy.uint64], return_polygons: bool = True) geopandas.GeoDataFrame[source]#

Convert EGI hashes to a GeoDataFrame.

Parameters:
uint_hash_iterlist or array of uint64

EGI hash values

return_polygonsbool

If True, return polygon geometries; if False, return point centroids

Returns:
GeoDataFrame

GeoDataFrame indexed by EGI hash with geometry column

Examples

>>> gdf = to_geodataframe(egi_hashes, return_polygons=True)
gedih3.egi.spatial.egi_h3_intersection(egi_tiles: geopandas.GeoDataFrame, h3_gdf: geopandas.GeoDataFrame) dict[source]#

Map EGI tiles to intersecting H3 partition cells using spatial index.

Maps each EGI tile to the union of:
  1. H3 cells whose polygon geometrically intersects the EGI tile, AND

  2. the ring-1 neighbors of those cells that are valid partitions.

Adding ring-1 neighbors closes a silent data-loss class on the EGI extraction path. The H3 database stores each shot in the partition cell_to_parent(latlng_to_cell(lon, lat, finer_res), partition_res), but partition assignment via geometric overlap of the H3 polygon uses the L3 latlng_to_cell boundary — and these two functions disagree at H3 cell boundaries (boundary-precision differs across resolutions). Shots at a partition boundary can therefore land in a storage cell whose polygon does not overlap their true EGI tile, so the unexpanded intersection silently misses them — observed in production: a single L3 partition with 1.84M shots had 84k (~5%) stored under a partition whose polygon did not intersect their true L12 tile. Including ring-1 neighbors closes this gap because the “fat-partition” extent is bounded by one neighbor-cell width.

Parameters:
egi_tilesGeoDataFrame

EGI tiles (typically level 12), indexed by EGI hash

h3_gdfGeoDataFrame

H3 partition cells, indexed by H3 ID (string)

Returns:
dict

Mapping of EGI tile hash -> list of H3 IDs (with ring-1 expansion).

Examples

>>> egi_tiles = aoi_tiles(region)
>>> h3_gdf = h3_parts_to_gdf(h3_ids)
>>> egi_to_h3 = egi_h3_intersection(egi_tiles, h3_gdf)
>>> for egi_id, h3_list in egi_to_h3.items():
...     # Load data from h3_list files for egi_id tile