Skip to content

yggdrasil.data.types.geo

geo

:class:GeoPointType — canonical struct of (lat, lon) float64.

A two-column nested struct used by curated tables that carry a location reference. The contract:

  • lat: float64 in WGS84 degrees, range [-90, 90].
  • lon: float64 in WGS84 degrees, range [-180, 180].

Both columns are non-nullable inside the struct — when a row has no location, mark the whole struct nullable via the parent :class:Field (geo_point("position", nullable=True)). Mixing NULL with one valid coordinate is meaningless.

Why a struct (not two flat columns)

Two flat columns (lat, lon) are fine when the location is a top-level attribute of the row. Switch to GeoPointType when:

  • the row carries multiple locations (origin, destination) and flat naming would proliferate (origin_lat / origin_lon / destination_lat / destination_lon reads worse than two GeoPoint columns),
  • a downstream sink (Arrow, Parquet, JSON, GeoJSON encoder, frontend map plugin) speaks the {"lat": …, "lon": …} shape natively,
  • a list-of-points column (points: list<struct<lat, lon, …>>) is the shape — see :func:geo_point below.

For flat-column curated rows the column-naming convention from ygg-curated-views (lat: float64, lon: float64 at the top level) still applies — they're equivalent payloads, pick whichever reads better at the call site.

Implementation

:data:GEO_POINT_TYPE is a pre-built :class:StructType instance the rest of the codebase imports as a singleton; building a fresh StructType per call would defeat the cast-registry's exact-match fast path. :func:geo_point is the corresponding Field factory so callers don't have to repeat the field args (nullable, metadata, tags).

geo_point

geo_point(
    name: str,
    *,
    nullable: bool = True,
    comment: Optional[str] = None,
    metadata: Optional[Mapping[Union[bytes, str], Any]] = None,
    tags: Optional[Mapping[Union[bytes, str], Any]] = None
) -> "Field"

Build a :class:Field of the canonical :data:GEO_POINT_TYPE.

nullable flips on the struct — the inner lat / lon children stay non-nullable so partial-coordinate rows (one of the two NULL) can't slip through.

Example::

from yggdrasil.data import Field, Schema, geo_point

ORIGIN_DESTINATION_SCHEMA = Schema.from_fields([
    Field("trip_id", DataType.string(), nullable=False),
    geo_point("origin",      comment="Pickup point, WGS84."),
    geo_point("destination", comment="Drop-off point, WGS84."),
])

is_geo_point_type

is_geo_point_type(value: Any) -> bool

Return True when value is the canonical GeoPoint shape.

Matches a :class:StructType with exactly the two children lat: float64 + lon: float64 (any nullability, any extra metadata). Useful for downstream code that wants to emit a GeoJSON / map-plugin representation for these and only these struct columns.