py/facett_demo/panes/map_pane.py
"""Sweden MAP pane — the REAL facett OSM 2D navigator, embedded as wasm.
This pane renders **no map of its own**. It fetches geometry from korp-server and
hands it to the `osm2d` component in the `facet-wrapped` registry, which is the very
same `facett_geomap::OsmView` the native `facett-demo` paints — compiled to wasm and
mounted as a live egui canvas. One implementation, two targets: the Python demo and
the Rust demo cannot drift, because there is only one renderer.
It previously re-implemented the map in pydeck. That lookalike drifted immediately:
pydeck's default `map_provider=CARTO` drew a third-party WORLD basemap under our
data, so a correctly-clipped Sweden appeared to include Africa. The data was never
wrong — the second renderer was.
Data source: korp-server ``KorpControl.MapQuery`` (the via-server GeoParquet render
path) over the region asset chosen via ``KorpControl.Assets``. The server prunes
row-groups to the viewport and returns only visible geometry; the raw OSM tags ride
along so the COMPONENT applies its own feature classification and styling.
"""
from __future__ import annotations
import streamlit as st
from ..facet_host import facett_component, is_data_driven
from ..client import KorpClient, KorpUnavailable
#: The facett component this pane embeds (registry name in `facet-wrapped`).
COMPONENT = "osm2d"
def _scene_payload(scene, asset: str) -> dict:
"""korp `MapQueryReply` → the `osm2d` payload.
A pure re-shaping: flat coord runs and raw OSM tag JSON pass through untouched, so
the component does the classifying/styling — this pane never decides a colour.
"""
return {
"title": f"{asset} — korp MapQuery",
"points": [[p.lon, p.lat] for p in scene.points],
"ways": [
{"osm_id": w.osm_id, "coords": list(w.coords), "tags": w.tags}
for w in scene.ways
],
}
def render(client: KorpClient) -> None:
st.subheader("🗺 Sweden map — the real facett OSM 2D navigator")
st.caption(
"Renderer: `facet-wrapped` → `osm2d` (facett_geomap::OsmView, wasm) · "
"Data: korp-server `Assets` + `MapQuery`"
)
try:
assets, asset_err = client.assets()
except KorpUnavailable as e:
st.error(f"Server unreachable — map assets unavailable.\n\n`{e}`")
return
if asset_err:
st.warning(f"Asset listing partial (S3): `{asset_err}`")
names = [a["name"] for a in assets] or ["sweden"]
asset = st.selectbox("Region asset", names, index=0, key="map_asset")
lod = st.slider("Level of detail", 1, 12, 6, key="map_lod")
cap = st.slider("Max ways / points", 500, 8000, 4000, step=500, key="map_cap")
try:
scene = client.map_query(asset=asset, lod=lod, max_ways=cap, max_points=cap)
except KorpUnavailable as e:
st.error(
"Map render failed — the server could not read the region GeoParquet.\n\n"
f"`{e}`\n\n"
"This is the honest empty state (commonly: MinIO/S3 offline and no local asset)."
)
return
if not scene.ways and not scene.points:
st.warning(f"Server returned no geometry for `{asset}` in this viewport (honest empty).")
st.caption(scene.status)
return
c1, c2, c3, c4 = st.columns(4)
c1.metric("Ways", len(scene.ways))
c2.metric("Points", len(scene.points))
c3.metric("Row-groups", f"{scene.row_groups_scanned}/{scene.row_groups_total}")
c4.metric("Capped", "yes" if scene.truncated else "no")
if not is_data_driven(COMPONENT):
# The wasm bundle is missing or too old to accept data. Refuse loudly rather
# than fall back to a demo fixture that would look like live Sweden data.
st.error(
f"`{COMPONENT}` is not available as a data-driven facett component — the "
"`facet-wrapped` wasm bundle is missing or stale. Rebuild it with "
"`cargo xtask wrap-wasm`. Refusing to show a demo fixture in place of "
"your data."
)
return
# The REAL component renders korp's geometry. No basemap, no second renderer.
facett_component(COMPONENT, data=_scene_payload(scene, asset), height=620, key="osm2d_map")
st.caption(scene.status)