vibespatial.raster

vibespatial.raster – GPU-first raster processing alongside vector data.

Standalone package that extends vibespatial with raster operations:
  • OwnedRasterArray with HOST/DEVICE residency

  • GeoTIFF/COG IO via rasterio

  • Raster algebra (local + focal) on GPU

  • Zonal statistics via CCCL segmented reduce

  • Vector-to-raster rasterize via NVRTC kernel

  • Raster-to-vector polygonize pipeline

Install: pip install vibespatial-raster Usage: from vibespatial.raster import read_raster, zonal_stats

Submodules

Classes

GridSpec

Target grid definition for rasterize operations.

OwnedRasterArray

Owned raster buffer with HOST/DEVICE residency and diagnostic tracking.

PolygonizeSpec

Configuration for raster-to-vector polygonize operations.

RasterDeviceState

GPU-resident mirror of an OwnedRasterArray.

RasterDiagnosticEvent

RasterDiagnosticKind

Enum where members are also (and must be) strings

RasterMetadata

Raster metadata extracted without reading pixel data.

RasterPlan

Result of analyzing a raster against a VRAM budget.

RasterTileSpec

Defines how a large raster should be chunked for GPU processing.

RasterWindow

Defines a sub-window into a raster for partial reads.

TilingStrategy

Processing strategy for a raster given VRAM constraints.

ZonalSpec

Configuration for zonal statistics computation.

ZonalStatistic

Enum where members are also (and must be) strings

Functions

from_device(, crs)

Create an OwnedRasterArray directly from a device array (zero-copy when possible).

from_numpy(, crs, residency)

Create an OwnedRasterArray from a numpy array.

Package Contents

class vibespatial.raster.GridSpec

Target grid definition for rasterize operations.

static from_bounds(minx: float, miny: float, maxx: float, maxy: float, resolution: float, dtype: numpy.dtype | str = 'float64') GridSpec

Create a GridSpec from spatial bounds and pixel resolution.

static from_raster(raster: OwnedRasterArray) GridSpec

Create a GridSpec matching an existing raster’s grid.

affine: tuple[float, float, float, float, float, float]
dtype: numpy.dtype
fill_value: float | int = 0
height: int
width: int
class vibespatial.raster.OwnedRasterArray

Owned raster buffer with HOST/DEVICE residency and diagnostic tracking.

Follows the same residency model as OwnedGeometryArray: - Buffers start HOST-resident after creation - After first device use, buffers stay DEVICE-resident by default - Host materialization is explicit (to_numpy, __repr__) - All transfers are tracked via RasterDiagnosticEvent

device_band(band_index: int) object

Return a 2D CuPy view of a single band (zero-copy slice).

Parameters

band_indexint

0-indexed band index.

Returns

object

CuPy ndarray of shape (height, width) – a view into the device array, not a copy.

Raises

IndexError

If band_index is out of range for the raster’s band count.

device_data() object

Return device-resident CuPy array, transferring from host if needed.

device_nodata_mask() object

Return device-resident nodata mask, computing lazily.

diagnostics_report() dict
static from_band_stack(band_results: collections.abc.Sequence[OwnedRasterArray], *, source: OwnedRasterArray) OwnedRasterArray

Assemble a multiband OwnedRasterArray from per-band results.

Parameters

band_resultsSequence[OwnedRasterArray]

One single-band OwnedRasterArray per band, in order.

sourceOwnedRasterArray

Original raster whose affine, CRS, and nodata are propagated to the assembled result.

Returns

OwnedRasterArray

A new raster with shape (len(band_results), H, W) (or (H, W) when a single result is passed through unchanged).

Raises

ValueError

If band_results is empty, if dtypes mismatch across bands, if nodata values mismatch, or if spatial dimensions differ.

move_to(target: vibespatial.residency.Residency, *, trigger: vibespatial.residency.TransferTrigger = TransferTrigger.EXPLICIT_RUNTIME_REQUEST, reason: str = '') None

Move raster data to the target residency.

record_runtime_selection(selection: vibespatial.runtime.RuntimeSelection) None
to_numpy() numpy.ndarray

Return host-resident numpy array, transferring from device if needed.

affine: tuple[float, float, float, float, float, float]
property band_count: int
property bounds: tuple[float, float, float, float]

Return (minx, miny, maxx, maxy) from the affine transform.

crs: pyproj.CRS | None = None
data: numpy.ndarray
device_state: RasterDeviceState | None = None
diagnostics: list[RasterDiagnosticEvent] = []
dtype: numpy.dtype
property height: int
property metadata: RasterMetadata
nodata: float | int | None
property nodata_mask: numpy.ndarray

Boolean mask where True means nodata (invalid pixel).

For device-resident rasters whose host data has not been synced, this materializes host data first so the mask is computed from actual pixel values rather than uninitialized memory.

property pixel_count: int
residency: vibespatial.residency.Residency
runtime_history: list[vibespatial.runtime.RuntimeSelection] = []
property shape: tuple[int, Ellipsis]
property valid_mask: numpy.ndarray

Boolean mask where True means valid pixel.

property width: int
class vibespatial.raster.PolygonizeSpec

Configuration for raster-to-vector polygonize operations.

connectivity: int = 4
max_polygons: int | None = 1000000
simplify_tolerance: float | None = None
value_field: str = 'value'
class vibespatial.raster.RasterDeviceState

GPU-resident mirror of an OwnedRasterArray.

data: object
nodata_mask: object | None = None
class vibespatial.raster.RasterDiagnosticEvent
bytes_transferred: int = 0
detail: str
elapsed_seconds: float = 0.0
kind: RasterDiagnosticKind
residency: vibespatial.residency.Residency
visible_to_user: bool = False
class vibespatial.raster.RasterDiagnosticKind

Bases: enum.StrEnum

Enum where members are also (and must be) strings

CREATED = 'created'
MATERIALIZATION = 'materialization'
RUNTIME = 'runtime'
TRANSFER = 'transfer'
class vibespatial.raster.RasterMetadata

Raster metadata extracted without reading pixel data.

affine: tuple[float, float, float, float, float, float]
band_count: int
property bounds: tuple[float, float, float, float]

Return (minx, miny, maxx, maxy) from the affine transform.

crs: pyproj.CRS | None
driver: str = ''
dtype: numpy.dtype
height: int
nodata: float | int | None
property pixel_count: int
width: int
class vibespatial.raster.RasterPlan

Result of analyzing a raster against a VRAM budget.

Describes whether the raster can be processed whole or must be spatially tiled, and provides tile dimensions when tiling is needed.

estimated_vram_per_tile: int
halo: int
n_tiles: int
strategy: TilingStrategy
tile_shape: tuple[int, int] | None
class vibespatial.raster.RasterTileSpec

Defines how a large raster should be chunked for GPU processing.

tile_count(height: int, width: int) tuple[int, int]

Return (rows_of_tiles, cols_of_tiles) for the given raster dimensions.

overlap: int = 0
tile_height: int
tile_width: int
class vibespatial.raster.RasterWindow

Defines a sub-window into a raster for partial reads.

col_off: int
height: int
row_off: int
width: int
class vibespatial.raster.TilingStrategy

Bases: enum.StrEnum

Processing strategy for a raster given VRAM constraints.

TILED = 'tiled'
WHOLE = 'whole'
class vibespatial.raster.ZonalSpec

Configuration for zonal statistics computation.

normalized_stats() tuple[ZonalStatistic, Ellipsis]
stats: tuple[ZonalStatistic | str, Ellipsis] = ('count', 'sum', 'mean', 'min', 'max')
class vibespatial.raster.ZonalStatistic

Bases: enum.StrEnum

Enum where members are also (and must be) strings

COUNT = 'count'
MAX = 'max'
MEAN = 'mean'
MEDIAN = 'median'
MIN = 'min'
STD = 'std'
SUM = 'sum'
vibespatial.raster.from_device(device_data, *, nodata: float | int | None = None, affine: tuple[float, float, float, float, float, float] = (1.0, 0.0, 0.0, 0.0, -1.0, 0.0), crs: pyproj.CRS | None = None) OwnedRasterArray

Create an OwnedRasterArray directly from a device array (zero-copy when possible).

Parameters

device_data

CuPy ndarray or any object exposing __cuda_array_interface__. Wrapped via cupy.asarray (zero-copy if already CuPy).

nodatafloat | int | None

Nodata sentinel value.

affinetuple

6-element GDAL-style affine: (a, b, c, d, e, f).

crsCRS | None

Coordinate reference system.

vibespatial.raster.from_numpy(data: numpy.ndarray, *, nodata: float | int | None = None, affine: tuple[float, float, float, float, float, float] = (1.0, 0.0, 0.0, 0.0, -1.0, 0.0), crs: pyproj.CRS | None = None, residency: vibespatial.residency.Residency = Residency.HOST) OwnedRasterArray

Create an OwnedRasterArray from a numpy array.

Parameters

datanp.ndarray

Pixel data. Shape (height, width) for single-band or (bands, height, width) for multi-band.

nodatafloat | int | None

Nodata sentinel value.

affinetuple

6-element GDAL-style affine: (a, b, c, d, e, f) where pixel_x = a * col + b * row + c, pixel_y = d * col + e * row + f.

crsCRS | None

Coordinate reference system.

residencyResidency

Initial residency (HOST or DEVICE).