| Latest Release | Downloads | ||
| License |
|
People |
|
| Build Status | Coverage |
📍 Fast, Accurate Python library for Raster Operations
⚡ Extensible with Numba
⏩ Scalable with Dask
🎊 Free of GDAL / GEOS Dependencies
🌍 General-Purpose Spatial Processing, Geared Towards GIS Professionals
Xarray-Spatial implements common raster analysis functions using Numba and provides an easy-to-install, easy-to-extend codebase for raster analysis.
# via pip
pip install xarray-spatial
# via conda
conda install -c conda-forge xarray-spatialOnce you have xarray-spatial installed in your environment, you can use one of the following in your terminal (with the environment active) to download our examples and/or sample data into your local directory.
xrspatial examples : Download the examples notebooks and the data used.
xrspatial copy-examples : Download the examples notebooks but not the data. Note: you won't be able to run many of the examples.
xrspatial fetch-data : Download just the data and not the notebooks.
In all the above, the command will download and store the files into your current directory inside a folder named 'xrspatial-examples'.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
xarray-spatial grew out of the Datashader project, which provides fast rasterization of vector data (points, lines, polygons, meshes, and rasters) for use with xarray-spatial.
xarray-spatial does not depend on GDAL / GEOS, which makes it fully extensible in Python but does limit the breadth of operations that can be covered. xarray-spatial is meant to include the core raster-analysis functions needed for GIS developers / analysts, implemented independently of the non-Python geo stack.
Our documentation is still under construction, but docs can be found here.
Rasters are regularly gridded datasets like GeoTIFFs, JPGs, and PNGs.
In the GIS world, rasters are used for representing continuous phenomena (e.g. elevation, rainfall, distance), either directly as numerical values, or as RGB images created for humans to view. Rasters typically have two spatial dimensions, but may have any number of other dimensions (time, type of measurement, etc.)
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| Box Plot | Classifies values into bins based on box plot quartile boundaries | ✅️ | ✅ | ✅ | ✅ |
| Equal Interval | Divides the value range into equal-width bins | ✅️ | ✅ | ✅ | ✅ |
| Head/Tail Breaks | Classifies heavy-tailed distributions using recursive mean splitting | ✅️ | ✅ | ✅ | ✅ |
| Maximum Breaks | Finds natural groupings by maximizing differences between sorted values | ✅️ | ✅ | ✅ | ✅ |
| Natural Breaks | Optimizes class boundaries to minimize within-class variance (Jenks) | ✅️ | ✅ | ✅ | ✅ |
| Percentiles | Assigns classes based on user-defined percentile breakpoints | ✅️ | ✅ | ✅ | ✅ |
| Quantile | Distributes values into classes with equal observation counts | ✅️ | ✅ | ✅ | ✅ |
| Reclassify | Remaps pixel values to new classes using a user-defined lookup | ✅️ | ✅ | ✅ | ✅ |
| Std Mean | Classifies values by standard deviation intervals from the mean | ✅️ | ✅ | ✅ | ✅ |
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| Apply | Applies a custom function over a sliding neighborhood window | ✅️ | ✅️ | ||
| Hotspots | Identifies statistically significant spatial clusters using Getis-Ord Gi* | ✅️ | ✅️ | ✅️ | |
| Mean | Computes the mean value within a sliding neighborhood window | ✅️ | ✅️ | ✅️ | |
| Focal Statistics | Computes summary statistics over a sliding neighborhood window | ✅️ | ✅️ | ✅️ |
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| Atmospherically Resistant Vegetation Index (ARVI) | Vegetation index resistant to atmospheric effects using blue band correction | ✅️ | ✅️ | ✅️ | ✅️ |
| Enhanced Built-Up and Bareness Index (EBBI) | Highlights built-up areas and barren land from thermal and SWIR bands | ✅️ | ✅️ | ✅️ | ✅️ |
| Enhanced Vegetation Index (EVI) | Enhanced vegetation index reducing soil and atmospheric noise | ✅️ | ✅️ | ✅️ | ✅️ |
| Green Chlorophyll Index (GCI) | Estimates leaf chlorophyll content from green and NIR reflectance | ✅️ | ✅️ | ✅️ | ✅️ |
| Normalized Burn Ratio (NBR) | Measures burn severity using NIR and SWIR band difference | ✅️ | ✅️ | ✅️ | ✅️ |
| Normalized Burn Ratio 2 (NBR2) | Refines burn severity mapping using two SWIR bands | ✅️ | ✅️ | ✅️ | ✅️ |
| Normalized Difference Moisture Index (NDMI) | Detects vegetation moisture stress from NIR and SWIR reflectance | ✅️ | ✅️ | ✅️ | ✅️ |
| Normalized Difference Vegetation Index (NDVI) | Quantifies vegetation density from red and NIR band difference | ✅️ | ✅️ | ✅️ | ✅️ |
| Soil Adjusted Vegetation Index (SAVI) | Vegetation index with soil brightness correction factor | ✅️ | ✅️ | ✅️ | ✅️ |
| Structure Insensitive Pigment Index (SIPI) | Estimates carotenoid-to-chlorophyll ratio for plant stress detection | ✅️ | ✅️ | ✅️ | ✅️ |
| True Color | Composites red, green, and blue bands into a natural color image | ✅️ | ️ | ✅️ | ️ |
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| A* Pathfinding | Finds the least-cost path between two cells on a cost surface | ✅️ |
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| Allocation | Assigns each cell to the identity of the nearest source feature | ✅️ | ✅ | ||
| Direction | Computes the direction from each cell to the nearest source feature | ✅️ | ✅ | ||
| Proximity | Computes the distance from each cell to the nearest source feature | ✅️ | ✅ |
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| Polygonize | Converts contiguous regions of equal value into vector polygons | ✅️ |
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| Aspect | Computes downslope direction of each cell in degrees | ✅️ | ✅️ | ✅️ | ✅️ |
| Curvature | Measures rate of slope change (concavity/convexity) at each cell | ✅️ | ✅️ | ✅️ | ✅️ |
| Hillshade | Simulates terrain illumination from a given sun angle and azimuth | ✅️ | ✅️ | ||
| Slope | Computes terrain gradient steepness at each cell in degrees | ✅️ | ✅️ | ✅️ | ✅️ |
| Terrain Generation | Generates synthetic terrain elevation using fractal noise | ✅️ | ✅️ | ✅️ | |
| Viewshed | Determines visible cells from a given observer point on terrain | ✅️ | |||
| Perlin Noise | Generates smooth continuous random noise for procedural textures | ✅️ | ✅️ | ✅️ | |
| Bump Mapping | Adds randomized bump features to simulate natural terrain variation | ✅️ |
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| Apply | Applies a custom function to each zone in a classified raster | ✅️ | ✅️ | ||
| Crop | Extracts the bounding rectangle of a specific zone | ✅️ | |||
| Regions | Identifies connected regions of non-zero cells | ||||
| Trim | Removes nodata border rows and columns from a raster | ✅️ | |||
| Zonal Statistics | Computes summary statistics for a value raster within each zone | ✅️ | ✅️ | ||
| Zonal Cross Tabulate | Cross-tabulates agreement between two categorical rasters | ✅️ | ✅️ |
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
|---|---|---|---|---|---|
| Cell Stats | Computes summary statistics across multiple rasters per cell | ✅️ | |||
| Combine | Assigns unique IDs to each distinct combination across rasters | ✅️ | |||
| Lesser Frequency | Counts how many rasters have values less than a reference | ✅️ | |||
| Equal Frequency | Counts how many rasters have values equal to a reference | ✅️ | |||
| Greater Frequency | Counts how many rasters have values greater than a reference | ✅️ | |||
| Lowest Position | Identifies which raster has the minimum value at each cell | ✅️ | |||
| Highest Position | Identifies which raster has the maximum value at each cell | ✅️ | |||
| Popularity | Returns the value from the most common position across rasters | ✅️ | |||
| Rank | Ranks cell values across multiple rasters per cell | ✅️ |
import xarray as xr
from xrspatial import hillshade
my_dataarray = xr.DataArray(...)
hillshaded_dataarray = hillshade(my_dataarray)Most functions also accept an xr.Dataset. Single-input functions (surface, classification, focal, proximity) apply the operation to each data variable and return a Dataset. Multi-input functions (multispectral indices) accept a Dataset with band-name keyword arguments.
# Single-input: returns a Dataset with slope computed for each variable
slope_ds = slope(my_dataset)
# Multi-input: map Dataset variables to band parameters
ndvi_result = ndvi(my_dataset, nir='band_5', red='band_4')
# Zonal stats: columns prefixed by variable name
stats_df = zonal.stats(zones, my_dataset) # → elevation_mean, temperature_mean, ...Check out the user guide here.
xarray-spatial currently depends on Datashader, but will soon be updated to depend only on xarray and numba, while still being able to make use of Datashader output when available.
Within the Python ecosystem, many geospatial libraries interface with the GDAL C++ library for raster and vector input, output, and analysis (e.g. rasterio, rasterstats, geopandas). GDAL is robust, performant, and has decades of great work behind it. For years, off-loading expensive computations to the C/C++ level in this way has been a key performance strategy for Python libraries (obviously...Python itself is implemented in C!).
However, wrapping GDAL has a few drawbacks for Python developers and data scientists:
- GDAL can be a pain to build / install.
- GDAL is hard for Python developers/analysts to extend, because it requires understanding multiple languages.
- GDAL's data structures are defined at the C/C++ level, which constrains how they can be accessed from Python.
With the introduction of projects like Numba, Python gained new ways to provide high-performance code directly in Python, without depending on or being constrained by separate C/C++ extensions. xarray-spatial implements algorithms using Numba and Dask, making all of its source code available as pure Python without any "black box" barriers that obscure what is going on and prevent full optimization. Projects can make use of the functionality provided by xarray-spatial where available, while still using GDAL where required for other tasks.
Cite this code:
xarray-contrib/xarray-spatial, https://github.com/xarray-contrib/xarray-spatial, ©2020-2026.



























