API reference¶
Array API¶
One call, bbox in, aligned xarray out. Requires earthfetch[xarray].
earthfetch.load.load_dem ¶
load_dem(bbox: Sequence[float], resolution: str = '10m', crs: str = 'EPSG:4326', res: float | None = None, source: str = 'auto') -> xarray.DataArray
Load a DEM for a bbox as an xarray.DataArray — no files, no keys.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bbox
|
(min_lon, min_lat, max_lon, max_lat) in WGS84 degrees.
|
|
required |
resolution
|
USGS dataset ("1m", "10m", "30m", "5m-ak"); ignored for
|
the Copernicus source (always 30 m). |
'10m'
|
crs
|
output CRS ("EPSG:32612", "EPSG:5070", ...).
|
|
'EPSG:4326'
|
res
|
output pixel size in ``crs`` units; defaults to the native
|
resolution (converted to degrees for geographic CRSs). |
None
|
source
|
"usgs", "copernicus", or "auto" (USGS first, Copernicus
|
fallback outside the US). |
'auto'
|
Returns:
| Type | Description |
|---|---|
DataArray
|
float32 (y, x) elevation in meters, NaN nodata, with |
Source code in src/earthfetch/load.py
earthfetch.load.load_sentinel2 ¶
load_sentinel2(bbox: Sequence[float], bands: Sequence[str] = ('B04', 'B03', 'B02'), crs: str = 'EPSG:4326', res: float | None = None, item: dict | None = None, items: Sequence[dict] | None = None, start: str | None = None, end: str | None = None, max_cloud: float = 20.0, scale: bool = True) -> xarray.DataArray
Load Sentinel-2 L2A bands for a bbox as one aligned DataArray.
Pass one of: a single STAC item; a list of items (from
covering_scenes — mosaicked together to fill an AOI that spans
tile boundaries); or start/end dates, in which case the single
clearest scene in the range is used.
res defaults to the finest native resolution among bands.
scale=True (default) converts DNs to surface reflectance (0..1)
using STAC metadata — matching composite/time_series so indices
behave the same on every source; pass scale=False for raw DNs.
Returns a float32 DataArray (band, y, x), NaN nodata, with scene
metadata in attrs. Multi-band assets like TCI are not supported here —
use download_sentinel2 for those.
Source code in src/earthfetch/load.py
earthfetch.load.stack ¶
stack(bbox: Sequence[float], crs: str, res: float, bands: Sequence[str] = ('B04', 'B08'), start: str | None = None, end: str | None = None, max_cloud: float = 20.0, item: dict | None = None, dem_resolution: str = '10m', dem_source: str = 'auto', scale: bool = True) -> xarray.Dataset
DEM + Sentinel-2 bands on one pixel-aligned grid — ML-ready.
Sentinel-2 bands are surface reflectance (0..1) by default, matching the
rest of the array API; pass scale=False for raw DNs. Returns an
xarray.Dataset with a dem variable plus one variable per band
(B04, B08, ...), all float32 on the same (y, x) grid.
Source code in src/earthfetch/load.py
earthfetch._composite.composite ¶
composite(aoi, bands: Sequence[str] = ('B04', 'B03', 'B02'), start: str = None, end: str = None, crs: str = 'utm', res: float | None = None, method: str = 'median', mask_clouds: bool = True, max_cloud: float = 60.0, max_scenes: int = 8, scale: bool = True, clip: bool = None, source: str = 'sentinel2') -> xarray.DataArray
Cloud-free composite of Sentinel-2 or Landsat bands over a date range.
Searches every scene touching the AOI, keeps the max_scenes clearest
acquisition days (all MGRS tiles of each day, so seams disappear), masks
invalid pixels with the SCL layer, and reduces per pixel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aoi
|
bbox tuple, GeoJSON, .geojson path, shapely geometry, or place name.
|
|
required |
bands
|
ESA band ids. SCL/TCI are not composable inputs here.
|
|
('B04', 'B03', 'B02')
|
start
|
ISO dates bounding the search.
|
|
None
|
end
|
ISO dates bounding the search.
|
|
None
|
crs
|
output CRS; "utm" (default) picks the AOI's UTM zone.
|
|
'utm'
|
res
|
pixel size in CRS units; defaults to the finest native band res.
|
|
None
|
method
|
"median" (robust, default), "mean", or "first" (first valid,
|
clearest day first — fastest). |
'median'
|
mask_clouds
|
mask SCL classes {0,1,3,8,9,10} before compositing.
|
|
True
|
max_cloud
|
scene-level cloud prefilter for the search.
|
|
60.0
|
max_scenes
|
acquisition days to blend.
|
|
8
|
scale
|
convert DNs to surface reflectance (0..1) using STAC metadata.
|
|
True
|
clip
|
NaN-out pixels outside a polygon AOI. Default (None): clip
|
polygons you passed explicitly, but keep the full rectangle for geocoded place names (pass clip=True to cut to a city boundary). |
None
|
Returns:
| Type | Description |
|---|---|
DataArray
|
float32 (band, y, x), NaN nodata, with the scene ids and dates
used in |
Source code in src/earthfetch/_composite.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | |
earthfetch._terrain.terrain ¶
terrain(aoi, products=('dem', 'slope', 'aspect', 'hillshade'), resolution: str = '10m', crs: str = 'utm', res: float = None, source: str = 'auto', azimuth: float = 315.0, altitude: float = 45.0, clip: bool = None) -> xarray.Dataset
DEM + terrain derivatives for any AOI as an aligned Dataset.
products chooses among "dem" (meters), "slope" (degrees), "aspect"
(compass degrees), "hillshade" (0-255). Other args follow load_dem.
Source code in src/earthfetch/_terrain.py
earthfetch.naip.load_naip ¶
load_naip(aoi, bands: Sequence[str] = ('R', 'G', 'B'), crs: str = 'utm', res: float | None = None, year: int | None = None, clip: bool | None = None) -> xarray.DataArray
US aerial imagery for any AOI as an xarray.DataArray.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aoi
|
bbox, GeoJSON, .geojson path, shapely geometry, or place name.
|
|
required |
bands
|
subset of R, G, B, N (near-infrared).
|
|
('R', 'G', 'B')
|
crs
|
output CRS; "utm" picks the AOI's zone.
|
|
'utm'
|
res
|
pixel size in CRS units; defaults to 1 m (native is 0.6-1 m).
|
|
None
|
year
|
pin a survey year; default mosaics the newest available.
|
|
None
|
clip
|
NaN-out pixels outside a polygon AOI. Defaults to True for
|
polygons you pass explicitly, False for geocoded place names. |
None
|
Returns:
| Type | Description |
|---|---|
DataArray
|
float32 (band, y, x) of 0-255 values, NaN nodata. |
Source code in src/earthfetch/naip.py
earthfetch.timeseries.time_series ¶
time_series(aoi, bands: Sequence[str] = ('B04', 'B03', 'B02'), start: str = None, end: str = None, crs: str = 'utm', res: float | None = None, max_cloud: float = 60.0, mask_clouds: bool = True, scale: bool = True, max_steps: int = 50, freq: str | None = None, clip: bool = None) -> xarray.DataArray
Cloud-masked Sentinel-2 time series over a date range.
Each clear acquisition day becomes a time step; the day's MGRS tiles are mosaicked together (first valid pixel wins), cloud/shadow pixels are masked with SCL, and values are reflectance-scaled.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aoi
|
bbox tuple, GeoJSON, .geojson path, shapely geometry, or place name.
|
|
required |
bands
|
ESA band ids. SCL/TCI are not composable inputs here.
|
|
('B04', 'B03', 'B02')
|
start
|
ISO dates bounding the search.
|
|
None
|
end
|
ISO dates bounding the search.
|
|
None
|
crs
|
output CRS; "utm" (default) picks the AOI's UTM zone.
|
|
'utm'
|
res
|
pixel size in CRS units; defaults to the finest native band res.
|
|
None
|
max_cloud
|
scene-level cloud prefilter for the search.
|
|
60.0
|
mask_clouds
|
mask SCL classes {0,1,3,8,9,10} before stacking.
|
|
True
|
scale
|
convert DNs to surface reflectance (0..1) using STAC metadata.
|
|
True
|
max_steps
|
cap on acquisition days (time steps) returned.
|
|
50
|
freq
|
optional pandas offset alias ("MS", "W", "QS", ...) to resample
|
the time axis with a per-period median (e.g. monthly composites). |
None
|
clip
|
NaN-out pixels outside a polygon AOI (see ``composite``).
|
|
None
|
Returns:
| Type | Description |
|---|---|
DataArray
|
float32 (time, band, y, x), NaN nodata, |
Source code in src/earthfetch/timeseries.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |
earthfetch.load.elevation ¶
Elevation in meters at one or more (lon, lat) points.
The most direct question a DEM answers. Elevation is mixed-source:
with source="auto" (default) it uses USGS 3DEP inside the United
States and falls back to Copernicus GLO-30 everywhere else, so it works
worldwide. Pass with_source=True to also get which source was used.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
a single ``(lon, lat)``, a list of them, or GeoJSON
|
Point/MultiPoint (WGS84). |
required |
source
|
"usgs", "copernicus", or "auto".
|
|
'auto'
|
resolution
|
DEM resolution when the USGS source is used.
|
|
'10m'
|
with_source
|
also return the DEM source ("usgs" or "copernicus").
|
|
False
|
Returns:
| Type | Description |
|---|---|
float or ndarray
|
A float for a single point, else an array of elevations (NaN where
outside coverage). If |
Source code in src/earthfetch/load.py
Analysis¶
Extract values from any earthfetch raster at points or over polygons.
Requires the raster extra.
earthfetch.zonal.sample ¶
Read raster values at points (nearest pixel).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
an earthfetch DataArray (2D ``(y, x)`` or 3D ``(band, y, x)``).
|
|
required |
points
|
a single ``(lon, lat)``, a list of them, or GeoJSON
|
Point/MultiPoint/Feature/FeatureCollection (WGS84). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Shape |
Source code in src/earthfetch/zonal.py
earthfetch.zonal.zonal_stats ¶
Aggregate raster values within each polygon.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
an earthfetch DataArray (2D or banded 3D).
|
|
required |
polygons
|
GeoJSON Polygon/MultiPolygon/Feature/FeatureCollection, a
|
shapely geometry, or a list of any of these (WGS84). |
required |
stats
|
any of "mean", "min", "max", "std", "median", "sum", plus
|
"count" (number of valid pixels). |
('mean', 'min', 'max', 'std', 'count')
|
Returns:
| Type | Description |
|---|---|
list of dict
|
One dict per polygon. For a 2D input each dict maps stat name to
value; for a banded input it maps |
Source code in src/earthfetch/zonal.py
Interoperability¶
Bridge earthfetch results into the rioxarray / rasterio ecosystem.
Requires the interop extra (pip install earthfetch[interop]).
earthfetch.interop.to_rioxarray ¶
Attach the earthfetch CRS/transform so the .rio accessor works.
Returns the same object with its CRS written; rioxarray infers the
transform from the x/y coordinates. After this you can call any
.rio method::
da = ef.to_rioxarray(ef.composite("Moab, Utah", ...))
da.rio.to_raster("moab.tif")
da.rio.reproject("EPSG:4326")
Source code in src/earthfetch/interop.py
earthfetch.interop.reproject ¶
Reproject a DataArray/Dataset to dst_crs (via rioxarray).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
an earthfetch result (CRS taken from ``attrs``).
|
|
required |
dst_crs
|
target CRS, e.g. "EPSG:4326" or "EPSG:5070".
|
|
required |
resolution
|
output pixel size in ``dst_crs`` units; None keeps the
|
source resolution reprojected. |
None
|
resampling
|
"nearest", "bilinear", "cubic", "average", ... (rasterio).
|
|
'bilinear'
|
Returns:
| Type | Description |
|---|---|
DataArray or Dataset
|
The reprojected object, with a working |
Source code in src/earthfetch/interop.py
Spectral indices¶
Each accepts an xarray.Dataset (band-named variables) or a DataArray
with a band coordinate, and returns a named DataArray.
earthfetch.indices.normalized_difference ¶
Generic normalized difference (A - B)/(A + B) for any two bands.
Escape hatch beyond the twelve named indices, e.g.
normalized_difference(ds, "B03", "B08", name="ndwi").
Source code in src/earthfetch/indices.py
earthfetch.indices.ndvi ¶
Normalized Difference Vegetation Index: (NIR - Red)/(NIR + Red).
earthfetch.indices.ndwi ¶
Normalized Difference Water Index (McFeeters): (G - NIR)/(G + NIR).
earthfetch.indices.nbr ¶
earthfetch.indices.evi ¶
Enhanced Vegetation Index (needs reflectance, not raw DNs).
earthfetch.indices.savi ¶
Soil-Adjusted Vegetation Index (needs reflectance).
earthfetch.indices.ndmi ¶
Normalized Difference Moisture Index: (NIR - SWIR1)/(NIR + SWIR1).
earthfetch.indices.ndsi ¶
Normalized Difference Snow Index: (G - SWIR1)/(G + SWIR1).
earthfetch.indices.ndre ¶
earthfetch.indices.ndbi ¶
Normalized Difference Built-up Index: (SWIR1 - NIR)/(SWIR1 + NIR).
earthfetch.indices.gndvi ¶
earthfetch.indices.msavi ¶
Modified Soil-Adjusted Vegetation Index (needs reflectance).
Source code in src/earthfetch/indices.py
earthfetch.indices.bsi ¶
Bare Soil Index: ((SWIR1 + R) - (NIR + B)) / ((SWIR1 + R) + (NIR + B)).
Source code in src/earthfetch/indices.py
Export¶
Requires earthfetch[raster].
earthfetch.export.to_geotiff ¶
Write a DataArray/Dataset as a tiled, deflate-compressed GeoTIFF.
Source code in src/earthfetch/export.py
earthfetch.export.to_cog ¶
Write a DataArray/Dataset as a Cloud-Optimized GeoTIFF.
Source code in src/earthfetch/export.py
earthfetch.export.preview ¶
Quick-look PNG with a percentile stretch.
3-band inputs (e.g. B04,B03,B02 composites) render as RGB; single bands as grayscale. Returns the PNG path — open it, or embed it in a notebook.
Source code in src/earthfetch/export.py
earthfetch.export.show ¶
show(obj, ax=None, cmap: str = 'viridis', stretch: tuple = (2, 98), title: str | None = None, colorbar: bool = True)
Render a result inline with matplotlib — no file needed.
3-band inputs display as a percentile-stretched RGB; single bands (and
indices) as a colormapped image with a colorbar. Axes are in the data's
CRS units. Returns the matplotlib Axes.
Requires the plot extra: pip install earthfetch[plot].
Source code in src/earthfetch/export.py
Raster operations¶
earthfetch.raster.clip_reproject ¶
clip_reproject(paths: Sequence[str | PathLike], bbox: Sequence[float], dst_crs: str = 'EPSG:4326', out_path: str | PathLike = 'clipped.tif', resampling: Resampling = None) -> Path
Merge raster tiles, clip to a WGS84 bbox, reproject to dst_crs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
paths
|
one or more GeoTIFFs sharing a CRS (e.g. DEM tiles, one S2 band).
|
|
required |
bbox
|
(min_lon, min_lat, max_lon, max_lat) in WGS84 degrees.
|
|
required |
dst_crs
|
any CRS string pyproj understands ("EPSG:32612", "EPSG:5070"...).
|
|
'EPSG:4326'
|
out_path
|
output GeoTIFF path.
|
|
'clipped.tif'
|
Returns:
| Type | Description |
|---|---|
Path
|
The output GeoTIFF path. |
Source code in src/earthfetch/raster.py
Cache¶
earthfetch.utils.cache_dir ¶
The directory earthfetch caches downloads in.
Overridable with the EARTHFETCH_CACHE environment variable.
earthfetch.utils.cache_info ¶
Inspect the cache: {"path": str, "files": int, "bytes": int}.
Source code in src/earthfetch/utils.py
earthfetch.utils.clear_cache ¶
Delete everything in the earthfetch cache. Returns bytes freed.
Source code in src/earthfetch/utils.py
Exceptions¶
earthfetch.exceptions.EarthfetchError ¶
earthfetch.exceptions.TileNotFoundError ¶
Bases: EarthfetchError
No DEM tiles cover the requested bbox.
earthfetch.exceptions.NoScenesError ¶
Bases: EarthfetchError
No Sentinel-2 scenes match the search.
earthfetch.exceptions.BandNotFoundError ¶
Bases: EarthfetchError
Requested band/asset is not present in the scene.
earthfetch.exceptions.DownloadError ¶
Bases: EarthfetchError
A download failed or arrived truncated.
earthfetch.exceptions.MissingDependencyError ¶
Bases: EarthfetchError, ImportError
An optional dependency (rasterio, xarray) is required but missing.