"""Simple STAC visualizer using leafmap and TiTiler-pgSTAC."""
from typing import List, Optional
from urllib.parse import urlencode
import leafmap
[docs]
class STACVisualizer:
"""Visualize STAC data using leafmap and TiTiler-pgSTAC.
Simple wrapper around leafmap to add TiTiler-pgSTAC raster tiles.
Example:
>>> viz = STACVisualizer(
... titiler_endpoint="http://0.0.0.0:8081",
... api_key="your-api-key"
... )
>>>
>>> m = viz.visualize(
... collection="TCX8021",
... assets="asset",
... center=[23.750, 77.698],
... zoom=13,
... colormap_name="ndvi",
... rescale="50,200"
... )
>>> m
"""
def __init__(
self,
titiler_endpoint: str,
api_key: Optional[str] = None,
tile_matrix_set: str = "WebMercatorQuad",
api_key_param_name: str = "api_key",
):
"""Initialize the visualizer.
Args:
titiler_endpoint: TiTiler-pgSTAC base URL (e.g., 'http://0.0.0.0:8081')
api_key: Optional API key for authentication (added to tile URLs as query parameter)
tile_matrix_set: Tile matrix set (default: WebMercatorQuad)
api_key_param_name: Query parameter name for API key (default: 'api_key')
"""
self.endpoint = titiler_endpoint.rstrip("/")
self.api_key = api_key
self.tile_matrix_set = tile_matrix_set
self.api_key_param_name = api_key_param_name
[docs]
def build_tile_url(self, collection: str, assets: str, **params) -> str:
"""Build TiTiler tile URL.
Args:
collection: STAC collection ID
assets: Asset name(s) - comma-separated for multiple
**params: Additional TiTiler parameters (colormap_name, rescale, etc.)
Returns:
Tile URL template
Example:
>>> viz = STACVisualizer("http://0.0.0.0:8081")
>>> url = viz.build_tile_url(
... collection="TCX8021",
... assets="asset",
... colormap_name="ndvi",
... rescale="50,200"
... )
"""
# Base tile URL
base_url = (
f"{self.endpoint}/collections/{collection}/"
f"tiles/{self.tile_matrix_set}/{{z}}/{{x}}/{{y}}"
)
# Build query parameters
query_params = {"assets": assets}
query_params.update(params)
# Add API key if provided (as query parameter)
if self.api_key:
query_params[self.api_key_param_name] = self.api_key
# Build final URL
query_string = urlencode(query_params)
return f"{base_url}?{query_string}"
[docs]
def visualize(
self,
collection: str,
assets: str,
center: List[float],
zoom: int = 10,
layer_name: Optional[str] = None,
opacity: float = 0.8,
basemap: str = "OpenStreetMap",
**titiler_params,
) -> leafmap.Map:
"""Visualize a STAC collection.
Args:
collection: STAC collection ID
assets: Asset name(s) to visualize
center: Map center [lat, lon]
zoom: Map zoom level
layer_name: Custom layer name (default: collection ID)
opacity: Layer opacity (0-1)
basemap: Basemap name
**titiler_params: Additional TiTiler parameters (colormap_name, rescale, etc.)
Returns:
leafmap.Map instance
Example:
>>> viz = STACVisualizer("http://0.0.0.0:8081")
>>> m = viz.visualize(
... collection="TCX8021",
... assets="asset",
... center=[23.750, 77.698],
... zoom=13,
... colormap_name="ndvi",
... rescale="50,200"
... )
>>> m
"""
# Create map
m = leafmap.Map(center=center, zoom=zoom)
# Add basemap
if basemap:
m.add_basemap(basemap)
# Build tile URL
tile_url = self.build_tile_url(collection=collection, assets=assets, **titiler_params)
# Add TiTiler raster tiles
m.add_tile_layer(
url=tile_url,
name=layer_name or collection,
attribution="TiTiler-pgSTAC",
opacity=opacity,
)
return m
[docs]
def add_layer(
self,
map_instance: leafmap.Map,
collection: str,
assets: str,
layer_name: Optional[str] = None,
opacity: float = 0.8,
**titiler_params,
) -> leafmap.Map:
"""Add a layer to an existing map.
Args:
map_instance: Existing leafmap.Map instance
collection: STAC collection ID
assets: Asset name(s) to visualize
layer_name: Custom layer name
opacity: Layer opacity (0-1)
**titiler_params: Additional TiTiler parameters
Returns:
Updated leafmap.Map instance
Example:
>>> viz = STACVisualizer("http://0.0.0.0:8081")
>>> m = leafmap.Map(center=[23.750, 77.698], zoom=13)
>>> m = viz.add_layer(
... m,
... collection="TCX8021",
... assets="asset",
... colormap_name="ndvi"
... )
"""
# Build tile URL
tile_url = self.build_tile_url(collection=collection, assets=assets, **titiler_params)
# Add layer
map_instance.add_tile_layer(
url=tile_url,
name=layer_name or collection,
attribution="TiTiler-pgSTAC",
opacity=opacity,
)
return map_instance