Geospatial xarray extension powered by rasterio for raster data manipulation and analysis
—
Global configuration options, version information, exception handling, and utility functions for CRS conversion and coordinate management. These components provide configuration control and diagnostic capabilities for rioxarray.
Control rioxarray behavior through global configuration settings that affect file I/O, metadata handling, and spatial operations.
class set_options:
"""
Set global rioxarray options as context manager or permanent setting.
Parameters:
- export_grid_mapping: bool (default=True) - Export full CF grid mapping attributes
- skip_missing_spatial_dims: bool (default=False) - Skip operations on vars without spatial dims
Usage as context manager:
with rioxarray.set_options(export_grid_mapping=False):
# operations with modified settings
Usage for global settings:
rioxarray.set_options(export_grid_mapping=False)
"""import rioxarray
# Set options globally
rioxarray.set_options(export_grid_mapping=False)
rioxarray.set_options(skip_missing_spatial_dims=True)
# Use as context manager (temporary setting)
with rioxarray.set_options(export_grid_mapping=False):
# Operations here won't export full grid mapping
da = rioxarray.open_rasterio('file.tif')
da.rio.write_crs(inplace=True) # Only writes crs_wkt and spatial_ref
# Settings revert after context manager
# Configure for performance (skip CF grid mapping for speed)
rioxarray.set_options(export_grid_mapping=False)
# Configure for datasets with missing spatial dimensions
rioxarray.set_options(skip_missing_spatial_dims=True)Display comprehensive version and system information for debugging and environment verification.
def show_versions() -> None:
"""
Print useful debugging information including rioxarray version,
dependencies, and system information.
Output includes:
- rioxarray version and main dependencies (rasterio, xarray, GDAL, GEOS, PROJ)
- Other Python dependencies (scipy, pyproj)
- System information (Python version, platform, executable path)
- GDAL and PROJ data paths
"""import rioxarray
# Display comprehensive version information
rioxarray.show_versions()
# Example output:
# rioxarray (0.19.0) deps:
# rasterio: 1.3.9
# xarray: 2024.7.0
# GDAL: 3.8.4
# GEOS: 3.12.1
# PROJ: 9.4.0
# PROJ DATA: /opt/conda/share/proj
# GDAL DATA: /opt/conda/share/gdal
#
# Other python deps:
# scipy: 1.11.4
# pyproj: 3.6.1
#
# System:
# python: 3.11.7
#executable: /opt/conda/bin/python
# machine: Linux-5.15.0-91-generic-x86_64
# Use in scripts for debugging
try:
da = rioxarray.open_rasterio('problem_file.tif')
except Exception as e:
print("Error occurred. Environment info:")
rioxarray.show_versions()
raiseComprehensive exception classes for handling different types of errors in geospatial operations.
# Base exception
class RioXarrayError(RuntimeError):
"""Base exception for errors in the rioxarray extension."""
# Data-related exceptions
class NoDataInBounds(RioXarrayError):
"""Raised when there is no data within the bounds for clipping a raster."""
class SingleVariableDataset(RioXarrayError):
"""Raised when operations expect multiple variables but dataset has only one."""
# Dimension-related exceptions
class DimensionError(RioXarrayError):
"""Base class for dimension-related errors."""
class MissingSpatialDimensionError(DimensionError):
"""Raised when required spatial dimensions cannot be found."""
class TooManyDimensions(DimensionError):
"""Raised when there are more dimensions than supported by the method."""
class InvalidDimensionOrder(DimensionError):
"""Raised when dimensions are not in the expected order."""
class OneDimensionalRaster(DimensionError):
"""Raised when a raster has only one spatial dimension."""
class DimensionMissingCoordinateError(RioXarrayError):
"""Raised when a dimension does not have supporting coordinates."""
# CRS-related exceptions
class MissingCRS(RioXarrayError):
"""Raised when CRS is required but missing from dataset."""import rioxarray
from rioxarray.exceptions import NoDataInBounds, MissingCRS, MissingSpatialDimensionError
try:
da = rioxarray.open_rasterio('file.tif')
# This might raise NoDataInBounds
geometry = {...} # Geometry outside raster bounds
clipped = da.rio.clip([geometry])
except NoDataInBounds as e:
print(f"No data in clipping area: {e}")
except MissingCRS as e:
print(f"CRS required but not found: {e}")
except MissingSpatialDimensionError as e:
print(f"Missing spatial dimensions: {e}")
except rioxarray.RioXarrayError as e:
print(f"General rioxarray error: {e}")
# Handle specific dimension errors
try:
# Operation requiring 2D data
da_1d = da.isel(x=0) # Creates 1D array
reprojected = da_1d.rio.reproject('EPSG:4326')
except OneDimensionalRaster as e:
print(f"Cannot reproject 1D raster: {e}")
# CRS validation
try:
da_no_crs = rioxarray.open_rasterio('no_crs_file.tif')
bounds = da_no_crs.rio.transform_bounds('EPSG:4326')
except MissingCRS as e:
print(f"Set CRS first: {e}")
da_no_crs.rio.set_crs('EPSG:4326') # Fix the issueHelper functions for working with coordinate reference systems and handling various CRS input formats.
def crs_from_user_input(crs_input: Any) -> rasterio.crs.CRS:
"""
Convert various CRS input formats to a standardized rasterio.crs.CRS object.
Handles transitions between GDAL versions and normalizes different CRS representations.
Parameters:
- crs_input: CRS in various formats (EPSG code, PROJ string, WKT, dict, CRS object)
Returns:
rasterio.crs.CRS: Standardized CRS object
Raises:
ValueError: If CRS input cannot be parsed
"""from rioxarray.crs import crs_from_user_input
# Convert various CRS input formats
crs1 = crs_from_user_input('EPSG:4326') # EPSG string
crs2 = crs_from_user_input(4326) # EPSG integer
crs3 = crs_from_user_input('+proj=longlat +datum=WGS84') # PROJ string
crs4 = crs_from_user_input({'init': 'epsg:4326'}) # Dictionary
crs5 = crs_from_user_input(crs1) # Already CRS object
# All produce equivalent results
print(crs1 == crs2 == crs3 == crs4 == crs5) # True
# Use in custom functions
def normalize_crs(input_crs):
"""Helper to ensure consistent CRS handling"""
return crs_from_user_input(input_crs)
# Handle invalid CRS
try:
invalid_crs = crs_from_user_input('INVALID:9999')
except ValueError as e:
print(f"Invalid CRS: {e}")import rioxarray
# Development settings (full debugging info)
rioxarray.set_options(
export_grid_mapping=True, # Full CF compliance
skip_missing_spatial_dims=False # Strict validation
)
# Production settings (optimized for performance)
rioxarray.set_options(
export_grid_mapping=False, # Skip expensive CF mapping
skip_missing_spatial_dims=True # Skip vars without spatial dims
)
# Context-specific settings
def process_for_analysis():
with rioxarray.set_options(export_grid_mapping=True):
# Full metadata for analysis
return rioxarray.open_rasterio('analysis_data.tif')
def process_for_display():
with rioxarray.set_options(export_grid_mapping=False):
# Fast loading for visualization
return rioxarray.open_rasterio('display_data.tif')import rioxarray
from rioxarray.exceptions import *
def robust_geospatial_operation(file_path, geometry):
"""Example of comprehensive error handling"""
try:
# Load data
da = rioxarray.open_rasterio(file_path)
# Validate CRS
if da.rio.crs is None:
raise MissingCRS("Dataset has no CRS defined")
# Perform clipping with error handling
try:
clipped = da.rio.clip([geometry])
except NoDataInBounds:
print("No data in geometry bounds, returning None")
return None
return clipped
except MissingSpatialDimensionError as e:
print(f"Spatial dimension issue: {e}")
# Try to fix dimension issues
if hasattr(da, 'squeeze'):
da = da.squeeze() # Remove single dimensions
return da.rio.clip([geometry])
raise
except TooManyDimensions as e:
print(f"Too many dimensions: {e}")
# Select first band if multi-band
if len(da.dims) > 2:
da = da.isel(band=0)
return da.rio.clip([geometry])
raise
except RioXarrayError as e:
print(f"Rioxarray error: {e}")
rioxarray.show_versions() # Debug info
raiseimport rioxarray
import os
# Environment-based configuration
def configure_rioxarray():
"""Configure rioxarray based on environment"""
# Check if in CI/testing environment
if os.getenv('CI') or os.getenv('PYTEST_CURRENT_TEST'):
rioxarray.set_options(
export_grid_mapping=False, # Faster tests
skip_missing_spatial_dims=True
)
# Check if debugging
elif os.getenv('DEBUG'):
rioxarray.set_options(
export_grid_mapping=True, # Full metadata
skip_missing_spatial_dims=False # Strict validation
)
# Production environment
else:
rioxarray.set_options(
export_grid_mapping=True, # CF compliance
skip_missing_spatial_dims=True # Performance
)
# Initialize configuration
configure_rioxarray()
# Display environment info for debugging
if os.getenv('DEBUG'):
rioxarray.show_versions()show_versions() when reporting issuesInstall with Tessl CLI
npx tessl i tessl/pypi-rioxarray