vibeproj¶
vibeProj — GPU-accelerated coordinate projection library.
Submodules¶
Attributes¶
Exceptions¶
Raised when input coordinates are invalid (wrong shape, dtype, etc.). |
|
Raised when a CRS input cannot be parsed or resolved. |
|
Raised when a CRS uses a projection method vibeProj doesn't support. |
|
Base exception for vibeProj errors. |
Classes¶
GPU-accelerated coordinate transformer. |
|
Validated error bounds relative to native fp64 execution. |
|
Device facts used by the strategy resolver. |
|
Immutable resolved decision, including fallback reason and workload size. |
|
Immutable public explanation for every stage in one transform direction. |
|
Immutable implementation metadata exposed by registry introspection. |
|
Operations with independently selectable transcendental strategies. |
Functions¶
Return the immutable built-in transcendental strategy registry. |
|
|
Return supported projections and their metadata. |
|
Pre-compile fused NVRTC kernels to eliminate first-call latency. |
Package Contents¶
- type vibeproj.CRSInput = int | str | tuple[str, int] | CRS¶
- exception vibeproj.CoordinateValidationError¶
Bases:
VibeProjectionErrorRaised when input coordinates are invalid (wrong shape, dtype, etc.).
- exception vibeproj.CRSResolutionError¶
Bases:
VibeProjectionErrorRaised when a CRS input cannot be parsed or resolved.
- exception vibeproj.UnsupportedProjectionError¶
Bases:
VibeProjectionErrorRaised when a CRS uses a projection method vibeProj doesn’t support.
- exception vibeproj.VibeProjectionError¶
Bases:
ExceptionBase exception for vibeProj errors.
- class vibeproj.Transformer(crs_from: vibeproj.crs.CRSInput, crs_to: vibeproj.crs.CRSInput, *, always_xy: bool = True, datum_shift: Literal['accurate', 'fast'] = 'accurate', epoch: float | None = None)¶
GPU-accelerated coordinate transformer.
transform(x, y) where x=lon, y=lat for geographic CRS (always_xy=True default)
direction=”FORWARD” or “INVERSE”
Accepts scalars, lists, numpy arrays, or cupy arrays
When CuPy is available and inputs are on GPU, transforms run on GPU. Otherwise falls back to NumPy on CPU.
Thread Safety¶
Transformer instances are safe to share across threads. NVRTC compilation is serialized on first use. Device-resident calls lease stream-specific scratch as needed.
transform_chunked()calls sharing one Transformer and CUDA device serialize around that device’s persistent staging workspace while retaining two-stream overlap within each call.- static from_crs(crs_from: vibeproj.crs.CRSInput, crs_to: vibeproj.crs.CRSInput, *, always_xy: bool = True, datum_shift: Literal['accurate', 'fast'] = 'accurate', epoch: float | None = None) Transformer¶
Create a Transformer from source and target CRS.
Parameters¶
- crs_from, crs_to :
EPSG integer (4326), string (“EPSG:4326”), or tuple ((“EPSG”, 4326)).
- always_xybool, default True
If True, input/output axis order is always (x, y) — i.e. (longitude, latitude) for geographic CRS and (easting, northing) for most projected CRS. Projected X/Y declarations are preserved: EPSG:5513 remains X=Southing, Y=Westing, matching pyproj. This otherwise follows shapely and geopandas conventions. If False, uses the CRS native axis order (pyproj default).
- datum_shiftstr, default “accurate”
“accurate” — use 15-parameter time-dependent Helmert when available, evaluating rate terms at the given epoch. Falls back to 7-parameter when no rates are present or no epoch can be resolved. “fast” — always use the base 7-parameter Helmert (ignores rate terms).
- epochfloat, optional
Decimal year at which to evaluate the time-dependent Helmert (e.g. 2024.0). Only used when datum_shift=”accurate”. If omitted, the source CRS coordinate epoch is used when available.
- property is_fused: bool¶
True if fused GPU kernels are available for this transform.
- explain_strategy(*, transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto', precision: str = 'auto', direction: Literal['FORWARD', 'INVERSE'] = 'FORWARD', device: vibeproj.transcendentals.DeviceCapability | None = None, workload_size: int | None = None) vibeproj.transcendentals.StrategyExplanation¶
Explain transcendental decisions for one transform direction.
The result is immutable and contains a decision for every projection stage plus Helmert when active. Passing device makes hardware policy tests deterministic; otherwise the current device is detected lazily.
precisionaccepts"auto","fp64","fp32", or"ds";transcendentalsaccepts"auto","native", or"accelerated". Passworkload_sizeto preview size-aware"auto"selection.Nonerepresents compilation/planning without a concrete array size and selects an otherwise-qualified accelerated implementation. This method does not materialize coordinate arrays.
- property accuracy: str¶
Rough accuracy classification for this transform.
Returns¶
- str
“sub-millimeter” — same datum, projection math only. “sub-5cm” — cross-datum with SVD-compressed grid correction. “sub-decimeter” — cross-datum with 15-param time-dependent Helmert evaluated at a known epoch. “sub-meter” — cross-datum with 7-param Helmert. “datum no-op (… m PROJ accuracy)” — PROJ selected an explicit no-op datum operation with meter-level expected accuracy. “degraded — no datum shift applied” — different datums; results may differ from pyproj by meters to hundreds of meters.
- compile(*, precision: str = 'auto', transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto') None¶
Pre-compile fused NVRTC kernels for this transformer.
precisionaccepts"auto","fp64","fp32", or"ds".transcendentalsaccepts"auto","native", or"accelerated"independently. Compilation has no concrete workload size, so"auto"selects an otherwise-qualified implementation without applying runtime crossover thresholds. This front-loads kernel compilation for every distinct projection/direction/implementation triple reachable in either transform direction; first-use stream scratch and chunk staging workspaces are still allocated lazily. No-op if CuPy is unavailable.
- transform(x: numpy.typing.ArrayLike, y: numpy.typing.ArrayLike, z: None = None, direction: Literal['FORWARD', 'INVERSE'] = 'FORWARD', *, precision: str = 'auto', transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto') tuple[Any, Any]¶
- transform(x: numpy.typing.ArrayLike, y: numpy.typing.ArrayLike, z: numpy.typing.ArrayLike, direction: Literal['FORWARD', 'INVERSE'] = 'FORWARD', *, precision: str = 'auto', transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto') tuple[Any, Any, Any]
Transform coordinates.
Parameters¶
- x, yscalar, list, numpy array, or cupy array
Input coordinates. With always_xy=True (default): x=longitude, y=latitude for geographic CRS and PROJ visualization order for projected CRS. EPSG:5513 remains X=Southing, Y=Westing. With always_xy=False: native CRS axis order.
- zscalar, list, numpy array, or cupy array, optional
Ellipsoidal height in meters. When a Helmert datum shift is active, z is transformed through the ECEF intermediate (correctness fix). When no datum shift is needed, z is passed through unchanged.
- directionstr
“FORWARD” or “INVERSE”.
- precision{“auto”, “fp64”, “fp32”, “ds”}
Numeric compute precision for fused GPU kernels.
- transcendentals{“auto”, “native”, “accelerated”}
Transcendental implementation policy, independent of precision.
"auto"uses the concrete input size and device capability when applying qualified acceleration crossover thresholds.
Returns¶
- tuple of arrays (or scalars if scalar input)
Transformed (x, y) or (x, y, z) if z was provided.
- transform_buffers(x: numpy.typing.ArrayLike, y: numpy.typing.ArrayLike, z: None = None, *, direction: Literal['FORWARD', 'INVERSE'] = 'FORWARD', out_x: numpy.typing.ArrayLike | None = None, out_y: numpy.typing.ArrayLike | None = None, out_z: numpy.typing.ArrayLike | None = None, precision: str = 'auto', transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto', stream: Any = None) tuple[Any, Any]¶
- transform_buffers(x: numpy.typing.ArrayLike, y: numpy.typing.ArrayLike, z: numpy.typing.ArrayLike, *, direction: Literal['FORWARD', 'INVERSE'] = 'FORWARD', out_x: numpy.typing.ArrayLike | None = None, out_y: numpy.typing.ArrayLike | None = None, out_z: numpy.typing.ArrayLike | None = None, precision: str = 'auto', transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto', stream: Any = None) tuple[Any, Any, Any]
Transform device-resident arrays with optional pre-allocated outputs.
Designed for integration with vibeSpatial’s OwnedGeometryArray. It skips scalar detection and dtype conversion. With pre-allocated outputs, repeated same-size GPU calls on a warmed, cached stream avoid output and correction-scratch allocation. First use, cache growth, and kernel compilation can still allocate.
Parameters¶
- x, ycupy.ndarray or numpy.ndarray
Coordinate arrays (fp64 storage per ADR-0002).
- zcupy.ndarray or numpy.ndarray, optional
Ellipsoidal height array. Transformed through Helmert when a datum shift is active; passed through unchanged by projection/SVD-only paths.
- directionstr
“FORWARD” or “INVERSE”.
- out_x, out_ycupy.ndarray or numpy.ndarray, optional
Pre-allocated fp64 output arrays. Avoids allocation.
- out_zcupy.ndarray or numpy.ndarray, optional
Pre-allocated fp64 output height array. Whenever
zis provided, this buffer is honored and returned for transformed or passthrough height paths.- precision{“auto”, “fp64”, “fp32”, “ds”}
Numeric compute precision for fused GPU kernels.
- transcendentals{“auto”, “native”, “accelerated”}
Hardware-aware transcendental implementation policy. This is independent of numeric compute precision.
"auto"uses the array size when applying qualified acceleration thresholds.- streamcupy.cuda.Stream, optional
CUDA stream for asynchronous execution.
Noneuses the current stream on the input array’s device; the legacy null stream is supported. Explicit streams from another device are rejected. The caller owns synchronization.
Returns¶
- tuple of arrays
Transformed
(out_x, out_y)or(out_x, out_y, z_out). Supplied output buffers are returned identically.
- transform_chunked(x: numpy.typing.ArrayLike, y: numpy.typing.ArrayLike, z: None = None, *, direction: Literal['FORWARD', 'INVERSE'] = 'FORWARD', chunk_size: int = 1000000, precision: str = 'auto', transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto') tuple[numpy.ndarray, numpy.ndarray]¶
- transform_chunked(x: numpy.typing.ArrayLike, y: numpy.typing.ArrayLike, z: numpy.typing.ArrayLike, *, direction: Literal['FORWARD', 'INVERSE'] = 'FORWARD', chunk_size: int = 1000000, precision: str = 'auto', transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto') tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
Transform large host-resident arrays in GPU-sized chunks.
Uses a double-buffered pipeline with pinned host memory and two CUDA streams to overlap transfers with GPU compute. Each Transformer keeps a grow-only workspace per CUDA device containing persistent streams, pinned buffers, and device buffers. Calls sharing that Transformer and device serialize around the complete workspace lifecycle; the two streams still overlap work within a call. Workspace and correction scratch allocation occurs on first use or growth and is reused by subsequent same-size calls.
Falls back to CPU
transform()when CuPy is not available.Parameters¶
- x, yarray-like
Input coordinate arrays (host memory).
- zarray-like, optional
Ellipsoidal height. Transformed through Helmert when a datum shift is active; passed through unchanged otherwise.
- directionstr
“FORWARD” or “INVERSE”.
- chunk_sizeint, default 1_000_000
Coordinates per GPU chunk. Larger values use more GPU memory but reduce per-chunk overhead. Size-aware
"auto"dispatch uses the planned buffer size once and reuses that decision for every chunk, including a smaller final chunk.- precision{“auto”, “fp64”, “fp32”, “ds”}
Numeric compute precision for fused GPU kernels.
- transcendentals{“auto”, “native”, “accelerated”}
Hardware-aware transcendental implementation policy, independent of precision.
Returns¶
- tuple of numpy.ndarray
Transformed (x, y) or (x, y, z) on the host.
- transform_bounds(left: float, bottom: float, right: float, top: float, *, densify_pts: int = 21, direction: Literal['FORWARD', 'INVERSE'] = 'FORWARD', precision: str = 'auto', transcendentals: vibeproj.transcendentals.TranscendentalPolicy = 'auto') tuple[float, float, float, float]¶
Transform a bounding box, densifying edges to handle projection curvature.
Densifies the four edges of the input bounding box, transforms all points, and returns the min/max envelope of the transformed result. This correctly handles non-linear projection distortion that would be missed by transforming only the four corners.
Parameters¶
- left, bottom, right, topfloat
Bounding box coordinates. With
always_xy=True(default): left/right are x (longitude), bottom/top are y (latitude).- densify_ptsint, default 21
Number of additional intermediate points per edge (not counting corner endpoints). Matches pyproj/GDAL convention: 0 means corners only, 21 (the default) adds 21 points between each pair of adjacent corners. Clamped to a minimum of 0.
- direction{“FORWARD”, “INVERSE”}
Transform direction.
- precision{“auto”, “fp64”, “fp32”, “ds”}
Numeric compute precision forwarded to the densified transform.
- transcendentals{“auto”, “native”, “accelerated”}
Hardware-aware transcendental implementation policy, independent of precision.
"auto"uses the densified point count.
Returns¶
- tuple of four floats
(left, bottom, right, top)of the transformed bounding box.
Notes¶
When the transformed result crosses the antimeridian (±180°), the returned
leftwill be greater thanright(e.g.left=153, right=-162), matching the pyproj convention.
- class vibeproj.AccuracyContract¶
Validated error bounds relative to native fp64 execution.
- reference: str¶
- max_horizontal_error_m: float¶
- max_vertical_error_m: float | None = None¶
- notes: str = ''¶
- max_physical_scale_m: float | None = None¶
- class vibeproj.DeviceCapability¶
Device facts used by the strategy resolver.
- backend: DeviceBackend¶
- compute_capability: tuple[int, int] | None = None¶
- fp32_to_fp64_ratio: int | None = None¶
- name: str | None = None¶
- device_id: int | None = None¶
- class vibeproj.StrategyDecision¶
Immutable resolved decision, including fallback reason and workload size.
- operation: TranscendentalOperation¶
- requested_policy: TranscendentalPolicy¶
- implementation_id: str¶
- family: str¶
- reason: str¶
- fallback: bool¶
- accuracy: AccuracyContract¶
- device: DeviceCapability¶
- domain: str¶
- workload_size: int | None¶
- class vibeproj.StrategyExplanation¶
Immutable public explanation for every stage in one transform direction.
- requested_policy: TranscendentalPolicy¶
- direction: Literal['FORWARD', 'INVERSE']¶
- device: DeviceCapability¶
- workload_size: int | None¶
- decisions: tuple[StrategyDecision, Ellipsis]¶
- class vibeproj.StrategyImplementation¶
Immutable implementation metadata exposed by registry introspection.
min_elementsis the runtime crossover used by"auto"after device, domain, and precision qualification. Explicit"accelerated"requests do not apply that size threshold.- implementation_id: str¶
- operation: TranscendentalOperation¶
- family: str¶
- supported_policies: tuple[TranscendentalPolicy, Ellipsis]¶
- supported_backends: tuple[DeviceBackend, Ellipsis]¶
- supported_compute_capabilities: tuple[tuple[int, int], Ellipsis]¶
- min_fp32_to_fp64_ratio: int | None¶
- supported_compute_precisions: tuple[ComputePrecision, Ellipsis]¶
- min_elements: int¶
- domains: tuple[str, Ellipsis]¶
- accuracy: AccuracyContract¶
- native_fallback: bool¶
- priority: int = 0¶
- class vibeproj.TranscendentalOperation¶
Bases:
str,enum.EnumOperations with independently selectable transcendental strategies.
- HELMERT = 'helmert'¶
- PROJECTION = 'projection'¶
- TMERC_FORWARD = 'tmerc.forward'¶
- vibeproj.TranscendentalPolicy¶
- vibeproj.list_transcendental_strategies() tuple[StrategyImplementation, Ellipsis]¶
Return the immutable built-in transcendental strategy registry.
Entries expose stable IDs, hardware/domain/precision qualifications,
min_elementscrossover thresholds, accuracy contracts, and native fallback behavior. Returning a tuple of frozen dataclasses prevents callers from changing global dispatch policy.
- vibeproj.list_projections() dict[str, dict]¶
Return supported projections and their metadata.
Returns¶
- dict[str, dict]
Keys are internal projection names. Each value has: - “methods”: list of pyproj method names that map to this projection - “fused”: True if a GPU-accelerated fused kernel is available
- vibeproj.warm_up(projections: list[str] | None = None, *, precision: str = 'auto', transcendentals: transcendentals.TranscendentalPolicy = 'auto') None¶
Pre-compile fused NVRTC kernels to eliminate first-call latency.
Parameters¶
- projectionslist of str, optional
Projection names to compile (e.g. [“tmerc”, “webmerc”]). If None, compiles all supported projections.
- precision{“auto”, “fp64”, “fp32”, “ds”}
Compute precision:
"auto","fp64","fp32", or"ds".- transcendentals{“auto”, “native”, “accelerated”}
Hardware-aware transcendental implementation policy, independent of compute precision. Warm-up has no concrete workload size, so
"auto"selects an otherwise-qualified implementation without applying runtime crossover thresholds.
Notes¶
This compiles fused projection kernels. Per-Transformer correction scratch, pinned staging buffers, device buffers, and persistent chunk streams remain lazily allocated on first use or growth. Module warm-up has no CRS domain; qualified
tmercwarm-up therefore includes both generic-TM native and forward-UTM accelerated variants.Examples¶
>>> import vibeproj >>> vibeproj.warm_up(["tmerc", "webmerc"]) # selective >>> vibeproj.warm_up() # all projections