vibespatial.geometry.owned

Attributes

Classes

DiagnosticKind

Enum where members are also (and must be) strings

BufferSharingMode

Enum where members are also (and must be) strings

DiagnosticEvent

FamilyGeometryBuffer

GeoArrowBufferView

MixedGeoArrowView

DeviceFamilyGeometryBuffer

DeviceMetadataState

Device-resident copies of the three routing metadata arrays.

OwnedGeometryDeviceState

OwnedGeometryArray

Columnar geometry storage with optional device-resident metadata.

Functions

unique_tag_pairs(→ list[tuple[int, int]])

Extract unique (left_tag, right_tag) pairs without Python-level iteration.

normalize_buffer_sharing_mode(→ BufferSharingMode)

from_shapely_geometries(→ OwnedGeometryArray)

from_wkb(→ OwnedGeometryArray)

from_geoarrow(→ OwnedGeometryArray)

concat_owned_scatter(→ OwnedGeometryArray)

Scatter replacement rows into base at indices, returning a new array.

build_device_resident_owned(→ OwnedGeometryArray)

Construct an OwnedGeometryArray from device buffers without touching host.

Module Contents

vibespatial.geometry.owned.cp = None
vibespatial.geometry.owned.NULL_TAG = -1
vibespatial.geometry.owned.FAMILY_TAGS: dict[vibespatial.geometry.buffers.GeometryFamily, int]
vibespatial.geometry.owned.TAG_FAMILIES
vibespatial.geometry.owned.unique_tag_pairs(left_tags: numpy.ndarray, right_tags: numpy.ndarray) list[tuple[int, int]]

Extract unique (left_tag, right_tag) pairs without Python-level iteration.

Works with both numpy and CuPy arrays. Packs two int8 tags into one int16 and calls the array library’s unique, then unpacks the small result (at most 36 pairs for 6 geometry families) on the host.

This replaces the set(zip(left.tolist(), right.tolist())) anti-pattern which forces a full-array D->H transfer and O(n) Python iteration.

Precondition: tag values must be non-negative and fit in int8 (0..127). Callers must filter null rows (NULL_TAG = -1) before calling.

class vibespatial.geometry.owned.DiagnosticKind

Enum where members are also (and must be) strings

CREATED = 'created'
TRANSFER = 'transfer'
MATERIALIZATION = 'materialization'
RUNTIME = 'runtime'
CACHE = 'cache'
class vibespatial.geometry.owned.BufferSharingMode

Enum where members are also (and must be) strings

COPY = 'copy'
SHARE = 'share'
AUTO = 'auto'
class vibespatial.geometry.owned.DiagnosticEvent
kind: DiagnosticKind
detail: str
residency: vibespatial.runtime.residency.Residency
visible_to_user: bool = False
elapsed_seconds: float = 0.0
bytes_transferred: int = 0
class vibespatial.geometry.owned.FamilyGeometryBuffer
family: vibespatial.geometry.buffers.GeometryFamily
schema: vibespatial.geometry.buffers.GeometryBufferSchema
row_count: int
x: numpy.ndarray
y: numpy.ndarray
geometry_offsets: numpy.ndarray
empty_mask: numpy.ndarray
part_offsets: numpy.ndarray | None = None
ring_offsets: numpy.ndarray | None = None
bounds: numpy.ndarray | None = None
host_materialized: bool = True
class vibespatial.geometry.owned.GeoArrowBufferView
family: vibespatial.geometry.buffers.GeometryFamily
x: numpy.ndarray
y: numpy.ndarray
geometry_offsets: numpy.ndarray
empty_mask: numpy.ndarray
part_offsets: numpy.ndarray | None = None
ring_offsets: numpy.ndarray | None = None
bounds: numpy.ndarray | None = None
shares_memory: bool = False
class vibespatial.geometry.owned.MixedGeoArrowView
validity: numpy.ndarray
tags: numpy.ndarray
family_row_offsets: numpy.ndarray
families: dict[vibespatial.geometry.buffers.GeometryFamily, GeoArrowBufferView]
shares_memory: bool = False
class vibespatial.geometry.owned.DeviceFamilyGeometryBuffer
family: vibespatial.geometry.buffers.GeometryFamily
x: vibespatial.cuda._runtime.DeviceArray
y: vibespatial.cuda._runtime.DeviceArray
geometry_offsets: vibespatial.cuda._runtime.DeviceArray
empty_mask: vibespatial.cuda._runtime.DeviceArray
part_offsets: vibespatial.cuda._runtime.DeviceArray | None = None
ring_offsets: vibespatial.cuda._runtime.DeviceArray | None = None
bounds: vibespatial.cuda._runtime.DeviceArray | None = None
class vibespatial.geometry.owned.DeviceMetadataState

Device-resident copies of the three routing metadata arrays.

When residency=DEVICE, these arrays live on GPU and the corresponding host numpy arrays in OwnedGeometryArray may be None. Accessing the host properties triggers a lazy D->H transfer.

validity: vibespatial.cuda._runtime.DeviceArray
tags: vibespatial.cuda._runtime.DeviceArray
family_row_offsets: vibespatial.cuda._runtime.DeviceArray
class vibespatial.geometry.owned.OwnedGeometryDeviceState
validity: vibespatial.cuda._runtime.DeviceArray
tags: vibespatial.cuda._runtime.DeviceArray
family_row_offsets: vibespatial.cuda._runtime.DeviceArray
families: dict[vibespatial.geometry.buffers.GeometryFamily, DeviceFamilyGeometryBuffer]
row_bounds: vibespatial.cuda._runtime.DeviceArray | None = None
class vibespatial.geometry.owned.OwnedGeometryArray(validity: numpy.ndarray | None, tags: numpy.ndarray | None, family_row_offsets: numpy.ndarray | None, families: dict[vibespatial.geometry.buffers.GeometryFamily, FamilyGeometryBuffer], residency: vibespatial.runtime.residency.Residency = Residency.HOST, diagnostics: list[DiagnosticEvent] | None = None, runtime_history: list[vibespatial.runtime.RuntimeSelection] | None = None, geoarrow_backed: bool = False, shares_geoarrow_memory: bool = False, device_adopted: bool = False, device_state: OwnedGeometryDeviceState | None = None, device_metadata: DeviceMetadataState | None = None, _row_count: int | None = None)

Columnar geometry storage with optional device-resident metadata.

The three routing metadata arrays – validity, tags, and family_row_offsets – are exposed as properties. When the array is device-resident, the host numpy copies may be None internally; accessing any property lazily transfers from GPU to CPU, preserving full backward compatibility for host consumers while allowing GPU-only pipelines to avoid the D->H transfer entirely.

families
residency
diagnostics: list[DiagnosticEvent] = None
runtime_history: list[vibespatial.runtime.RuntimeSelection] = None
geoarrow_backed = False
shares_geoarrow_memory = False
device_adopted = False
device_state = None
property validity: numpy.ndarray
property tags: numpy.ndarray
property family_row_offsets: numpy.ndarray
property row_count: int
family_has_rows(family: vibespatial.geometry.buffers.GeometryFamily) bool

Check whether family has at least one geometry row to process.

Reads from whichever side is authoritative: device_state when populated, host FamilyGeometryBuffer otherwise. This avoids the bug where host stubs with host_materialized=False report empty offsets even when device buffers have real data.

move_to(target: vibespatial.runtime.residency.Residency | str, *, trigger: vibespatial.runtime.residency.TransferTrigger | str, reason: str | None = None) OwnedGeometryArray
record_runtime_selection(selection: vibespatial.runtime.RuntimeSelection) None
cache_bounds(bounds: numpy.ndarray) None
cache_device_bounds(family: vibespatial.geometry.buffers.GeometryFamily, bounds: vibespatial.cuda._runtime.DeviceArray) None
classmethod concat(arrays: list[OwnedGeometryArray]) OwnedGeometryArray

Concatenate multiple OwnedGeometryArrays at the buffer level.

Stays host-resident and avoids any Shapely materialization. All input arrays are ensured to have host state before concatenation. Device state is not carried over; the caller can move the result to device if needed.

diagnostics_report() dict[str, Any]
take(indices: numpy.ndarray) OwnedGeometryArray

Return a new OwnedGeometryArray containing only the rows at indices.

Operates entirely at the buffer level – no Shapely round-trip. When the array is DEVICE-resident or indices are already on device (CuPy / __cuda_array_interface__), dispatches to device_take() to keep all gathering on GPU. Otherwise returns a HOST-resident array.

device_take(indices) OwnedGeometryArray

Device-side take — all gathering stays on GPU.

Accepts numpy or CuPy indices/mask. Returns a DEVICE-resident OwnedGeometryArray with host buffers marked host_materialized=False. The host side is lazily populated by _ensure_host_state() on demand.

to_shapely() list[object | None]
to_wkb(*, hex: bool = False) list[bytes | str | None]
to_geoarrow(*, sharing: BufferSharingMode | str = BufferSharingMode.COPY) MixedGeoArrowView
vibespatial.geometry.owned.normalize_buffer_sharing_mode(mode: BufferSharingMode | str) BufferSharingMode
vibespatial.geometry.owned.from_shapely_geometries(geometries: list[object | None] | tuple[object | None, Ellipsis], *, residency: vibespatial.runtime.residency.Residency = Residency.HOST) OwnedGeometryArray
vibespatial.geometry.owned.from_wkb(values: list[bytes | str | None] | tuple[bytes | str | None, Ellipsis], *, on_invalid: str = 'raise', residency: vibespatial.runtime.residency.Residency = Residency.HOST) OwnedGeometryArray
vibespatial.geometry.owned.from_geoarrow(view: MixedGeoArrowView, *, residency: vibespatial.runtime.residency.Residency = Residency.HOST, sharing: BufferSharingMode | str = BufferSharingMode.COPY) OwnedGeometryArray
vibespatial.geometry.owned.concat_owned_scatter(base: OwnedGeometryArray, replacement: OwnedGeometryArray, indices: numpy.ndarray) OwnedGeometryArray

Scatter replacement rows into base at indices, returning a new array.

Returns a new OwnedGeometryArray with the same row count as base where: - rows at indices come from replacement (in order) - all other rows come from base

len(indices) must equal replacement.row_count.

Operates entirely at the buffer level — no Shapely materialisation. When both inputs are host-resident the result is host-resident; when both are device-resident, use device_concat_owned_scatter() instead (future work).

vibespatial.geometry.owned.build_device_resident_owned(*, device_families: dict[vibespatial.geometry.buffers.GeometryFamily, DeviceFamilyGeometryBuffer], row_count: int, tags: numpy.ndarray, validity: numpy.ndarray, family_row_offsets: numpy.ndarray) OwnedGeometryArray

Construct an OwnedGeometryArray from device buffers without touching host.

This is the canonical factory for producing device-resident results from GPU kernels. Host-side FamilyGeometryBuffers are created with empty coordinate stubs (host_materialized=False); actual data lives only in the device_state. Lazy _ensure_host_state will copy on demand if the caller ever needs Shapely objects.

Parameters

device_families

Per-family device buffers produced by a GPU kernel.

row_count

Total number of rows (geometries) in the output.

tags

int8 array of family tags, length row_count.

validity

bool array, length row_count.

family_row_offsets

int32 array mapping global row index to family-local row index.