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

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.

seed_all_validity_cache(→ None)

Seed the per-row validity cache with an all-valid mask.

build_updated_device_family_buffer(...)

Rebuild a device family buffer after a span-preserving coordinate rewrite.

build_updated_host_family_buffer(→ FamilyGeometryBuffer)

Rebuild a host family buffer after a span-preserving coordinate rewrite.

normalize_buffer_sharing_mode(→ BufferSharingMode)

from_shapely_geometries(→ OwnedGeometryArray)

build_null_owned_array(→ OwnedGeometryArray)

Build an all-null OwnedGeometryArray without materializing Shapely.

from_wkb(→ OwnedGeometryArray)

from_geoarrow(→ OwnedGeometryArray)

concat_owned_scatter(→ OwnedGeometryArray)

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

concatenate_owned_arrays(→ OwnedGeometryArray)

Concatenate owned geometry arrays without materializing geometry objects.

device_concat_owned_scatter(→ OwnedGeometryArray)

Scatter replacement rows into base without leaving the device.

build_device_resident_owned(→ OwnedGeometryArray)

Construct an OwnedGeometryArray from device buffers without touching host.

forward_result_metadata(...)

Forward metadata for a device result without forcing host copies.

tile_single_row(→ OwnedGeometryArray)

Create an N-row owned array from a 1-row owned array.

materialize_broadcast(→ OwnedGeometryArray)

Physically replicate coordinate buffers in a tiled owned array.

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.

vibespatial.geometry.owned.seed_all_validity_cache(owned: OwnedGeometryArray | None) None

Seed the per-row validity cache with an all-valid mask.

Exact overlay/clip results and successful post-repair outputs are already normalized geometry buffers. Marking them valid avoids re-running full OGC validity scans when those public results feed immediately into another polygon operation.

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
dense_single_ring_width: int | None = None
vibespatial.geometry.owned.build_updated_device_family_buffer(family: vibespatial.geometry.buffers.GeometryFamily, device_buf: DeviceFamilyGeometryBuffer, d_x_out: vibespatial.cuda._runtime.DeviceArray, d_y_out: vibespatial.cuda._runtime.DeviceArray, d_new_offsets: vibespatial.cuda._runtime.DeviceArray) DeviceFamilyGeometryBuffer

Rebuild a device family buffer after a span-preserving coordinate rewrite.

vibespatial.geometry.owned.build_updated_host_family_buffer(family: vibespatial.geometry.buffers.GeometryFamily, host_buf: FamilyGeometryBuffer, x_out: numpy.ndarray, y_out: numpy.ndarray, new_offsets: numpy.ndarray) FamilyGeometryBuffer

Rebuild a host family buffer after a span-preserving coordinate rewrite.

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, _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
property is_indexed_view: bool

True when this array is a virtual indexed view over a compact base.

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.

When ALL inputs are device-resident (residency == DEVICE) and have device state populated, concatenation is performed entirely on GPU using CuPy – no D->H transfer occurs. The result is a device-resident OGA with lazy host stubs.

When ANY input is host-resident (or lacks device state), falls back to the existing host-side concatenation path.

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.

When the indices have high repetition (many output rows mapping to few unique source rows), returns a virtual indexed view that stores only the unique rows and an index map, avoiding the physical coordinate copy. This is transparent to consumers: kernel dispatch triggers _resolve(), and to_shapely() expands via cheap Python object references.

Memory pressure is handled by the ADR-0040 tiered allocator: Tier B (default) retries with gc.collect on OOM; Tier C (opt-in) uses CUDA managed memory for datasets exceeding VRAM.

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.

When indices have high repetition, returns a virtual indexed view instead of performing a full device gather. See take() for the design rationale.

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.build_null_owned_array(row_count: int, *, residency: vibespatial.runtime.residency.Residency = Residency.HOST) OwnedGeometryArray

Build an all-null OwnedGeometryArray without materializing Shapely.

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 device-resident, dispatches to device_concat_owned_scatter() so the result stays on GPU.

vibespatial.geometry.owned.concatenate_owned_arrays(arrays: list[OwnedGeometryArray]) OwnedGeometryArray

Concatenate owned geometry arrays without materializing geometry objects.

vibespatial.geometry.owned.device_concat_owned_scatter(base: OwnedGeometryArray, replacement: OwnedGeometryArray, indices: numpy.ndarray | vibespatial.cuda._runtime.DeviceArray) OwnedGeometryArray

Scatter replacement rows into base without leaving the device.

vibespatial.geometry.owned.build_device_resident_owned(*, device_families: dict[vibespatial.geometry.buffers.GeometryFamily, DeviceFamilyGeometryBuffer], row_count: int, tags: numpy.ndarray | vibespatial.cuda._runtime.DeviceArray, validity: numpy.ndarray | vibespatial.cuda._runtime.DeviceArray, family_row_offsets: numpy.ndarray | vibespatial.cuda._runtime.DeviceArray, execution_mode: str | None = None) 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.

execution_mode

Optional execution mode marker. When set to "gpu", host numpy metadata arrays are rejected so GPU-path callers cannot silently re-upload metadata through this factory.

vibespatial.geometry.owned.forward_result_metadata(owned: OwnedGeometryArray) tuple[numpy.ndarray | vibespatial.cuda._runtime.DeviceArray, numpy.ndarray | vibespatial.cuda._runtime.DeviceArray, numpy.ndarray | vibespatial.cuda._runtime.DeviceArray]

Forward metadata for a device result without forcing host copies.

When the source already has device metadata, reuse those arrays directly so downstream device-resident builders do not pay a D->H->D round-trip. Otherwise, preserve the historical host-copy behavior for host-only inputs.

vibespatial.geometry.owned.tile_single_row(owned: OwnedGeometryArray, n: int) OwnedGeometryArray

Create an N-row owned array from a 1-row owned array.

The coordinate buffers (x, y) and offset arrays inside each FamilyGeometryBuffer are shared with the original – only the three routing metadata arrays (validity, tags, family_row_offsets) are replicated. This makes the operation O(N) in tiny int8/int32/bool metadata, not O(N * vertex_count) in fp64 coordinates, eliminating the host-side materialization bottleneck for scalar broadcast (nsf.3/nsf.4).

Parameters

owned

Must have row_count == 1.

n

Desired number of output rows.

Returns

OwnedGeometryArray

An n-row array where every row references the same geometry as the single input row. The family buffers have row_count == 1 and every row’s family_row_offsets entry is 0.

vibespatial.geometry.owned.materialize_broadcast(tiled: OwnedGeometryArray) OwnedGeometryArray

Physically replicate coordinate buffers in a tiled owned array.

tile_single_row() creates an N-row metadata facade that shares the 1-row coordinate buffers. GPU kernels that index into family buffers by global row index require family_buf.row_count == n. This function converts the metadata-only tile into a fully- materialized array where each family buffer has n physical rows with replicated coordinate data.

The operation is O(N * vertices_per_geometry) in coordinate copies but avoids per-element Python loops and the Shapely round-trip that would otherwise be required. It is only called for the GPU path of broadcast-right constructive operations.

Parameters

tiled

An OwnedGeometryArray produced by tile_single_row() (N-row metadata, 1-row family buffers with all family_row_offsets == 0).

Returns

OwnedGeometryArray

Same metadata but with physically replicated family buffers where family_buf.row_count == tiled.row_count.