ODC Geo - Geometry Classes and Operations

raw JSON →
0.5.1 verified Mon Apr 27 auth: no python

odc-geo provides geometry classes and operations for geospatial data, built on top of Shapely, Rasterio, and Xarray. It is part of the Open Data Cube ecosystem. Version 0.5.1 released 2025-04-27. Release cadence: irregular, major changes every few months.

pip install odc-geo
error ModuleNotFoundError: No module named 'odc.geo'
cause odc-geo is not installed or installed in a different environment.
fix
Run: pip install odc-geo
error ImportError: cannot import name 'GeoBox' from 'odc.geo'
cause An outdated version (<0.4.0) where GeoBox was not in the public API or path changed.
fix
Upgrade: pip install --upgrade odc-geo. Use correct import: from odc.geo import GeoBox
error TypeError: 'NoneType' object is not subscriptable when accessing .shape
cause GeoBox shape was not set or is None; often from missing resolution in from_bbox.
fix
Ensure you provide resolution or shape when creating GeoBox. Example: GeoBox.from_bbox(bbox, crs=crs, resolution=0.1)
error ValueError: Expected 'shapely' >=2.0, found version ...
cause odc-geo requires Shapely 2.0+; older versions are incompatible.
fix
Upgrade Shapely: pip install --upgrade shapely
breaking In v0.5.0, xarray became a required dependency. Code that previously imported odc.geo without xarray installed will break.
fix Ensure xarray is installed: pip install xarray
gotcha GeoBox dimensions order is (height, width), not (width, height). Using incorrect order leads to swapped axes.
fix Always specify shape as (height, width) when constructing GeoBox.
deprecated Importing from odc.geo._deprecated or using legacy functions like `odc.geo.geom.polygon` is deprecated and may be removed in future.
fix Use the public API: from odc.geo import Geometry instead.
breaking odc.geo.crs.CRS was changed: the constructor now enforces stricter validation of EPSG codes. Invalid codes raise an error instead of silently using WGS84.
fix Ensure EPSG codes are valid integer or string (e.g., 'EPSG:4326'). Use CRS('EPSG:4326') not CRS(4326) (though the latter may still work).

Create a GeoBox from bounding box, generate a zero-filled DataArray, and reproject.

from odc.geo import GeoBox, CRS
from odc.geo.xr import xr_zeros
import os

# Define a GeoBox
crs = CRS('EPSG:4326')
geobox = GeoBox.from_bbox((-10, 10, 10, -10), crs=crs, resolution=0.1)
print(geobox)

# Create an xarray DataArray with geospatial info
da = xr_zeros(geobox)
print(da)

# Basic reproject (if dask available)
if 'PYTEST_CURRENT_TEST' not in os.environ:
    da_reproj = da.odc.reproject('EPSG:3857', resolution=100)
    print(da_reproj)