xarray-spatial

repository·main·Indexed 21 days ago

https://github.com/xarray-contrib/xarray-spatial

A fast, extensible Python library for raster analysis built on xarray. It provides over 150 functions for spatial processing—including hydrology, fire behavior, and multispectral indices—with automatic dispatching across NumPy, Dask, and CuPy (GPU) backends. The library includes a native GeoTIFF and Cloud Optimized GeoTIFF (COG) reader/writer that does not require GDAL, as well as tools for reprojection, merging, and resampling rasters.

Tokens
108.9K
Snippets
391
Records
484
Agent score
72%

What's inside xarray-spatial

  1. Overview of Xarray-Spatial

    main

    Xarray-Spatial is a library that implements common raster analysis functions using Numba. It is designed to be easy to install and extend, providing core GIS functions for developers and analysts.

    Key characteristics:

    • Performance: Uses Numba for high-performance raster analysis.
    • Independence: Does not depend on GDAL or GEOS, making it fully extensible in Python, though this limits the breadth of operations compared to the full non-Python geo stack.
    • Integration: Grew out of the Datashader project, which provides fast rasterization of vector data (points, lines, polygons, meshes, and rasters) for use with xarray-spatial.
  2. Performance comparison: xarray-spatial reproject vs rioxarray

    main

    The reproject functionality in xarray-spatial (using a numpy backend and Numba JIT) is benchmarked against rioxarray (using GDAL warp).

    Key Performance Insights

    • Resampling Methods: xarray-spatial typically shows significant speed advantages in bilinear and cubic resampling, especially during CRS transformations (e.g., EPSG:4326 to EPSG:3857).
    • Small to Medium Rasters: For smaller datasets (256x256 to 512x512), xarray-spatial is consistently faster across most resampling methods.
    • Large Rasters: For very large rasters (1024x1024 and above), rioxarray may become competitive or faster for nearest neighbor resampling, but xarray-spatial often maintains a lead in bilinear and cubic methods.
    • Identity Transforms: When performing an identity transform (same CRS), xarray-spatial is highly efficient, particularly with cubic and bilinear interpolation.
  3. What is xarray-spatial and how does it work?

    main

    xarray-spatial is a raster analysis library built on top of xarray. It provides over 150 functions for tasks such as surface analysis, hydrology, fire behavior, flood modeling, multispectral indices, proximity, classification, pathfinding, and interpolation.

    Key Characteristics

    • Data Format: Every function accepts an xr.DataArray as input and returns an xr.DataArray. This allows for seamless chaining of operations without manual data conversions.
    • Backend Dispatch: Functions automatically dispatch to one of four backends based on the input array type:
      • NumPy: For in-memory arrays.
      • Dask: For out-of-core chunked arrays.
      • CuPy: For GPU-accelerated arrays.
      • Dask+CuPy: For distributed GPU-accelerated arrays.
    • Implementation: Unlike many geospatial libraries, it does not depend on GDAL or GEOS. Instead, it uses Numba and Dask for compute functions, and pure Python/Numba for raster I/O, reprojection, and coordinate handling.
  4. How hydrology routing algorithms work

    main

    The hydrology module provides high-level wrapper functions for various tasks (flow direction, accumulation, etc.). You select the routing algorithm using the routing keyword argument.

    Supported routing algorithms:

    • 'd8': Default algorithm.
    • 'dinf': D-infinity routing.
    • 'mfd': Multiple Flow Direction routing.

    While you should use the top-level xrspatial functions for most tasks, the specific implementations for each algorithm are located in the xrspatial.hydro submodule (e.g., xrspatial.hydro.flow_direction_d8).

    import xrspatial
    # Example using 'dinf' routing
    fdir = xrspatial.flow_direction(dem, routing='dinf')
    acc = xrspatial.flow_accumulation(fdir, routing='dinf')
  5. Understand Dask laziness levels in xarray-spatial

    main

    When using xarray-spatial with Dask-backed DataArray objects, the library attempts to maintain laziness to support out-of-core processing. However, different algorithms have different memory requirements. Understanding these levels helps you plan pipelines and avoid memory errors.

    Laziness Levels

    • Fully lazy: The function returns a Dask array without triggering computation. These are safe for arbitrarily large datasets.
    • Partially lazy: The function computes small, bounded statistics (like scalars, quartiles, or a ~20K sample) during setup to configure the operation, then returns a Dask array for the main result. The heavy lifting remains lazy.
    • Fully materialized: The algorithm requires random access to the full array and calls .compute() internally. These functions will load the necessary data into memory. Use caution with large inputs.
  6. Understand the performance model of the reproject module

    main

    The reproject module splits work between pyproj for metadata and high-performance kernels (Numba/CUDA) for pixel-level operations.

    • pyproj (Low Cost): Used once per call for CRS metadata parsing, EPSG code lookups, and estimating the output grid extent via Transformer.transform() on boundary points.
    • Numba/CUDA (High Cost/Per-pixel): Handles the heavy lifting including coordinate transforms, resampling (bilinear, nearest-neighbor), datum grid interpolation (NTv2/NADCON), geoid undulation (EGM96/EGM2008), and Helmert datum shifts.
    • Note on Cubic Resampling: Currently uses scipy.ndimage.map_coordinates and is restricted to the CPU (no Numba/CUDA kernel available).
  7. Understand Rasterizer Benchmark Methodology

    main

    The rasterizer benchmarks compare xarray-spatial (using both numpy and cupy backends) against other libraries including datashader, geocube, and rasterio.

    Benchmarks are conducted across several dimensions:

    • Geometry Types:
      • Polygons: circles, irregular, rectangles, stars, donuts, multipolygons.
      • Lines: lines, multilines.
      • Points: points, multipoints.
    • Feature Counts (n): 50, 200, 1000, and 10000.
    • Output Resolutions: 100px to 4000px wide.

    Note that for Line and Point types, datashader uses a different API compared to the other libraries.

  8. Performance and consistency of merge()

    main

    The merge() method is used to combine overlapping tiles into a single mosaic. Benchmarks comparing xarray-spatial against rioxarray using a 'first' strategy (where overlapping areas are resolved by taking the first available pixel) show:

    • Small Tiles (256x256 to 512x512): xarray-spatial is significantly faster.
    • Large Tiles (2048x2048): rioxarray performs better for very large merges.
  9. Understand NaN behavior and nodata handling

    main

    The library uses NaN as the universal nodata sentinel. There is no option to use other values like -9999.

    NaN Propagation Rules:

    • Slope, aspect, hillshade: Any NaN neighbor produces a NaN output cell.
    • Focal mean/std: NaN neighbors are excluded from the calculation; the cell itself is still computed.
    • Zonal stats: NaN values are excluded from aggregation. An all-NaN zone returns NaN.
    • Hydrology (flow direction) & Pathfinding (A):* NaN cells are treated as impassable barriers.

    Edge Handling: When using boundary='nan', edge cells within the kernel radius of the raster boundary default to NaN. Use boundary='nearest' or boundary='reflect' to avoid this.