Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

GeoMap

A lightweight MapLibre GL map with three layer kinds — GeoJSON features, XYZ raster tiles and quantized grid rasters — and a built-in layer panel. Every trait is plain JSON, so the map renders the same in a live kernel and on a static page, and the reader can switch bands, stretch and colormaps with no kernel at all.

Import

from manywidgets import GeoMap, GridLayer
from manywidgets.geo_map import corners_from_bounds, corners_from_coords

Example

API

TraitTypeDefaultDescription
basemapUnicode'positron'“positron” | “dark-matter” | “voyager” | “satellite” | “osm” | “none” | “auto” (follows light/dark) | a style URL.
heightUnicode'480px'CSS height of the map.
view_stateDict—Camera as {longitude, latitude, zoom}; updated from the map on move.
fit_boundsListNone[west, south, east, north] to fit on load; None = fit all layers.
layersList—Layer specs (geojson | xyz | grid), drawn in list order.
layer_stateDict—Reader-adjustable per-layer state {id: {visible, opacity, active, range, colormap}} written by the panel.
selectedUnicode''Id of the selected GeoJSON feature (two-way).
hoveredUnicode''Id of the hovered GeoJSON feature (two-way).
controlsBoolTrueShow the built-in layer panel.
zoom_to_selectedBoolTrueFit the map to a feature when selected changes.
widget_idUnicode''Stable unique id used for cross-widget linking (auto-assigned).

Layers

  • add_geojson(data, id=..., id_property=..., tooltip=[...], fill=, line=, ...) — a FeatureCollection / Feature / Geometry dict, or anything with __geo_interface__ (a GeoDataFrame, a shapely geometry). Clicking a feature sets selected to its id (id_property, else the feature id, else its index); hovering sets hovered and shows the tooltip properties.

  • add_xyz(url, ...) — a {z}/{x}/{y} tile template (TiTiler tilejson tiles[0], NASA GIBS, OSM …). Tiles are fetched by the viewer’s browser, so the URL must work without credentials.

  • add_grid(GridLayer.from_arrays({...}, corners, ...)) — 2-D arrays quantized to one byte per pixel per band (0 = nodata), with optional RGB composites. corners are the image’s outer corners as [lon, lat] in TL, TR, BR, BL order; use corners_from_bounds(left, bottom, right, top, crs) or corners_from_coords(x, y, crs) (pip install "manywidgets[geo]" for the crs reprojection via pyproj). The quad is placed on the map without resampling, so a projected (e.g. UTM) window keeps its pixels.

Each layer’s reader-adjustable state (visibility, opacity, active band, stretch range, colormap) lives in layer_state, keyed by layer id — it is what the panel writes, and what you set from Python to choose the initial look.

Linking

selected / hovered are two-way strings, so a map and a Table stay in sync with a kernel-free link:

from ipywidgets import jslink
jslink((table, "selected"), (m, "selected"))

Size

The data of a grid layer is carried as base64 inside the widget state (≈1.33 × the raw bytes): an 800 × 800 band is ≈ 0.85 MB. GridLayer.nbytes reports it. The MapLibre bundle itself (≈ 0.8 MB) is stored once per GeoMap instance in an executed notebook’s widget state.