CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-rasterstats

Summarize geospatial raster datasets based on vector geometries

Pending
Overview
Eval results
Files

io-utilities.mddocs/

I/O and Data Utilities

Core input/output utilities and data handling classes that support rasterstats functionality. These utilities handle reading vector data from various sources, managing raster data access, and providing coordinate system transformations.

Capabilities

Raster Data Access

The Raster class provides unified access to raster data from files or numpy arrays.

from rasterstats.io import Raster

class Raster:
    """
    Raster abstraction for data access to 2/3D array-like things.
    
    Use as a context manager to ensure dataset gets closed properly.
    
    Parameters:
    - raster: 2/3D array-like data source (path to raster file or numpy array)
    - affine: Affine transformation (required if raster is ndarray)
    - nodata: Override nodata value (default: None)
    - band: Raster band number, counting from 1 (default: 1)
    """
    
    def __init__(self, raster, affine=None, nodata=None, band=1): ...
    
    def index(self, x, y):
        """
        Convert (x, y) coordinates in CRS to (row, column) indices.
        
        Parameters:
        - x: X coordinate in coordinate reference system
        - y: Y coordinate in coordinate reference system
        
        Returns:
        Tuple of (row, column) indices
        """
    
    def read(self, bounds=None, window=None, masked=False, boundless=True):
        """
        Read data from the raster source.
        
        Parameters:
        - bounds: Bounding box (w, s, e, n) (default: None)
        - window: Rasterio-style window ((row_start, row_stop), (col_start, col_stop)) (default: None)
        - masked: Return masked numpy array (default: False)
        - boundless: Allow reading beyond dataset extent (default: True)
        
        Returns:
        Raster object with updated affine and array info
        
        Raises:
        ValueError if both bounds and window specified or neither specified
        """
    
    # Context manager methods
    def __enter__(self): ...
    def __exit__(self, *args): ...

Vector Data Reading

Functions for reading vector data from various sources including files, GeoJSON, and geometric objects.

from rasterstats.io import read_features, read_featurecollection

def read_features(obj, layer=0):
    """
    Read vector features from various input sources.
    
    Supports:
    - File paths (Shapefile, GeoJSON, etc.)
    - GeoJSON strings or dictionaries
    - Feature collections
    - Iterables of feature-like objects
    - Objects with __geo_interface__
    - WKT/WKB geometry strings/bytes
    
    Parameters:
    - obj: Vector data source
    - layer: Layer index or name for multi-layer sources (default: 0)
    
    Returns:
    Iterator yielding GeoJSON-like Feature dictionaries
    
    Raises:
    ValueError if object is not a recognized source of features
    """

def read_featurecollection(obj, layer=0):
    """
    Read vector features and return as GeoJSON FeatureCollection.
    
    Parameters:
    - obj: Vector data source (same as read_features)
    - layer: Layer index or name (default: 0)
    
    Returns:
    GeoJSON FeatureCollection dictionary with all features loaded
    """

def parse_feature(obj):
    """
    Parse a single object into a GeoJSON-like Feature.
    
    Attempts to convert various input formats:
    - Objects with __geo_interface__
    - WKT/WKB strings/bytes
    - GeoJSON geometry or feature dictionaries
    
    Parameters:
    - obj: Object to parse as feature
    
    Returns:
    GeoJSON-like Feature dictionary
    
    Raises:
    ValueError if object cannot be parsed as a feature
    """

Coordinate and Window Utilities

Functions for coordinate system transformations and window calculations.

from rasterstats.io import rowcol, bounds_window, window_bounds

def rowcol(x, y, affine, op=math.floor):
    """
    Convert x/y coordinates to row/column indices.
    
    Parameters:
    - x: X coordinate
    - y: Y coordinate  
    - affine: Affine transformation
    - op: Rounding operation function (default: math.floor)
    
    Returns:
    Tuple of (row, column) indices
    """

def bounds_window(bounds, affine):
    """
    Create rasterio-style window from bounding box.
    
    Parameters:
    - bounds: Bounding box (west, south, east, north)
    - affine: Affine transformation
    
    Returns:
    Window tuple ((row_start, row_stop), (col_start, col_stop))
    """

def window_bounds(window, affine):
    """
    Calculate bounding box from rasterio-style window.
    
    Parameters:
    - window: Window tuple ((row_start, row_stop), (col_start, col_stop))
    - affine: Affine transformation
    
    Returns:
    Bounding box tuple (west, south, east, north)
    """

def beyond_extent(window, shape):
    """
    Check if window references pixels beyond raster extent.
    
    Parameters:
    - window: Window tuple ((row_start, row_stop), (col_start, col_stop))
    - shape: Raster shape tuple (height, width)
    
    Returns:
    Boolean indicating if window extends beyond raster bounds
    """

Array Utilities

Functions for handling boundless array operations and data access.

from rasterstats.io import boundless_array

def boundless_array(arr, window, nodata, masked=False):
    """
    Extract array data for window that may extend beyond array bounds.
    
    Areas outside the array extent are filled with nodata values.
    
    Parameters:
    - arr: Input numpy array (2D or 3D)
    - window: Window tuple ((row_start, row_stop), (col_start, col_stop))
    - nodata: Value to use for areas outside array bounds
    - masked: Return masked array (default: False)
    
    Returns:
    Numpy array (optionally masked) with data for requested window
    
    Raises:
    ValueError if array is not 2D or 3D
    """

Warning Classes

Custom warning classes for I/O operations.

from rasterstats.io import NodataWarning

class NodataWarning(UserWarning):
    """
    Warning raised for nodata handling issues.
    
    Issued when:
    - No nodata value is specified and default (-999) is used
    - Dataset masks are detected and masked reading is automatically enabled
    """

Usage Examples

Working with Raster Data

from rasterstats.io import Raster
from affine import Affine
import numpy as np

# Using file-based raster
with Raster("elevation.tif") as rast:
    # Get pixel indices for coordinates
    row, col = rast.index(100.5, 200.7)
    
    # Read full raster
    full_data = rast.read()
    
    # Read specific window
    window = ((10, 50), (20, 60))
    subset = rast.read(window=window, masked=True)
    
    # Read by bounding box
    bounds = (100, 200, 150, 250)  # w, s, e, n
    clipped = rast.read(bounds=bounds, boundless=True)

# Using numpy array
raster_array = np.random.rand(100, 100) * 1000
transform = Affine.translation(0, 100) * Affine.scale(1, -1)

with Raster(raster_array, affine=transform, nodata=-999) as rast:
    subset = rast.read(bounds=(10, 10, 50, 50))
    print(f"Shape: {subset.array.shape}")
    print(f"Affine: {subset.affine}")

Reading Vector Data

from rasterstats.io import read_features, read_featurecollection

# Read from shapefile
features = list(read_features("watersheds.shp"))
print(f"Found {len(features)} features")

# Read from GeoJSON string
geojson_str = '''{"type": "Point", "coordinates": [100, 200]}'''
point_features = list(read_features(geojson_str))

# Read from feature collection
fc = read_featurecollection("polygons.geojson")
print(f"FeatureCollection with {len(fc['features'])} features")

# Read from list of geometries
geometries = [
    {"type": "Point", "coordinates": [100, 200]},
    {"type": "Point", "coordinates": [150, 250]}
]
point_list = list(read_features(geometries))

# Handle multi-layer sources
layers = list(read_features("multilayer.gpkg", layer="roads"))

Coordinate Transformations

from rasterstats.io import rowcol, bounds_window, window_bounds
from affine import Affine
import math

# Create sample transform
transform = Affine.translation(100, 200) * Affine.scale(1, -1)

# Convert coordinates to pixel indices
row, col = rowcol(105.5, 195.3, transform)
print(f"Pixel location: row {row}, col {col}")

# Using ceiling operation for different rounding
row_ceil, col_ceil = rowcol(105.5, 195.3, transform, op=math.ceil)

# Create window from bounds
bounds = (100, 150, 200, 250)  # w, s, e, n  
window = bounds_window(bounds, transform)
print(f"Window: {window}")

# Get bounds back from window
calculated_bounds = window_bounds(window, transform)
print(f"Bounds: {calculated_bounds}")

Handling Boundless Operations

from rasterstats.io import boundless_array, beyond_extent
import numpy as np

# Create sample array
arr = np.random.rand(50, 50) * 100
shape = arr.shape

# Define window that extends beyond array
large_window = ((45, 65), (45, 65))  # Extends 15 pixels beyond

if beyond_extent(large_window, shape):
    print("Window extends beyond array bounds")

# Extract data with nodata fill
result = boundless_array(arr, large_window, nodata=-999, masked=True)
print(f"Result shape: {result.shape}")
print(f"Original array shape: {arr.shape}")
print(f"Nodata pixels: {(result == -999).sum()}")

Types

from typing import Union, List, Dict, Any, Optional, Tuple, Iterator
from numpy import ndarray
from affine import Affine

# Input types
VectorSource = Union[str, Dict, List[Dict], bytes]  # Various vector input formats
RasterSource = Union[str, ndarray]  # File path or numpy array
LayerSpec = Union[int, str]  # Layer index or name
GeometryDict = Dict[str, Any]  # GeoJSON geometry dictionary
FeatureDict = Dict[str, Any]  # GeoJSON feature dictionary

# Coordinate types
Bounds = Tuple[float, float, float, float]  # (west, south, east, north)
Window = Tuple[Tuple[int, int], Tuple[int, int]]  # ((row_start, row_stop), (col_start, col_stop))
Coordinates = Tuple[float, float]  # (x, y) coordinate pair
PixelIndices = Tuple[int, int]  # (row, column) indices

# Array types
BoundlessArray = Union[ndarray, np.ma.MaskedArray]  # Regular or masked array
ArrayShape = Tuple[int, int]  # (height, width) for 2D arrays

Install with Tessl CLI

npx tessl i tessl/pypi-rasterstats

docs

cli.md

index.md

io-utilities.md

point-queries.md

zonal-statistics.md

tile.json