diff --git a/bindings/pydeck/examples/maplibre_globe.py b/bindings/pydeck/examples/maplibre_globe.py new file mode 100644 index 00000000000..b7b974c99e1 --- /dev/null +++ b/bindings/pydeck/examples/maplibre_globe.py @@ -0,0 +1,57 @@ +""" +GlobeView +========= + +Over 33,000 power plants of the world plotted by their production capacity (given by height) +and fuel type (green if renewable) on a MapLibre globe view. + +This example demonstrates using MapLibre's globe projection with deck.gl layers by setting +map_provider='maplibre' and map_projection='globe'. The globe view uses MapLibre's +MapboxOverlay with interleaved rendering for optimal performance. +""" +import pydeck as pdk +import pandas as pd + +POWER_PLANTS = "https://raw.githubusercontent.com/ajduberstein/geo_datasets/master/global_power_plant_database.csv" + +df = pd.read_csv(POWER_PLANTS) + + +def is_green(fuel_type): + """Return a green RGB value if a facility uses a renewable fuel type""" + if fuel_type.lower() in ("nuclear", "water", "wind", "hydro", "biomass", "solar", "geothermal"): + return [10, 230, 120] + return [230, 158, 10] + + +df["color"] = df["primary_fuel"].apply(is_green) + +# Use MapView with a globe projection +view_state = pdk.ViewState(latitude=51.47, longitude=0.45, zoom=0) + +layers = [ + pdk.Layer( + "ColumnLayer", + id="power-plant", + data=df, + get_elevation="capacity_mw", + get_position=["longitude", "latitude"], + elevation_scale=100, + pickable=True, + auto_highlight=True, + radius=20000, + get_fill_color="color", + ), +] + +deck = pdk.Deck( + initial_view_state=view_state, + tooltip={"text": "{name}, {primary_fuel} plant, {country}"}, + layers=layers, + # Use MapLibre with globe projection + map_provider="maplibre", + map_style="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json", + map_projection="globe", +) + +deck.to_html("maplibre_globe.html", css_background_color="black", offline=True) diff --git a/bindings/pydeck/pydeck/bindings/base_map_provider.py b/bindings/pydeck/pydeck/bindings/base_map_provider.py index 87beb629c19..9a38c1729c3 100644 --- a/bindings/pydeck/pydeck/bindings/base_map_provider.py +++ b/bindings/pydeck/pydeck/bindings/base_map_provider.py @@ -7,3 +7,4 @@ class BaseMapProvider(Enum): MAPBOX = "mapbox" GOOGLE_MAPS = "google_maps" CARTO = "carto" + MAPLIBRE = "maplibre" diff --git a/bindings/pydeck/pydeck/bindings/deck.py b/bindings/pydeck/pydeck/bindings/deck.py index d08abaf56cd..511e3193fc3 100644 --- a/bindings/pydeck/pydeck/bindings/deck.py +++ b/bindings/pydeck/pydeck/bindings/deck.py @@ -45,6 +45,7 @@ def __init__( parameters=None, widgets=None, show_error=False, + map_projection=None, ): """This is the renderer and configuration for a deck.gl visualization, similar to the `Deck `_ class from deck.gl. @@ -63,7 +64,7 @@ def __init__( ``MAPBOX_API_KEY``, ``GOOGLE_MAPS_API_KEY``, and ``CARTO_API_KEY`` can be set instead of hardcoding the key here. map_provider : str, default 'carto' If multiple API keys are set (e.g., both Mapbox and Google Maps), inform pydeck which basemap provider to prefer. - Values can be ``carto``, ``mapbox`` or ``google_maps`` + Values can be ``carto``, ``mapbox``, ``google_maps``, or ``maplibre``. map_style : str or dict, default 'dark' One of 'light', 'dark', 'road', 'satellite', 'dark_no_labels', and 'light_no_labels', a URI for a basemap style, which varies by provider, or a dict that follows the Mapbox style `specification `_. @@ -87,6 +88,10 @@ def __init__( show_error : bool, default False If ``True``, will display the error in the rendered output. Otherwise, will only show error in browser console. + map_projection : str, default None + Map projection to use with ``map_provider='maplibre'``. + Values can be ``'globe'`` or ``'mercator'``. Defaults to ``'mercator'`` if not specified. + Only supported with ``map_provider='maplibre'``. .. _Deck: https://deck.gl/docs/api-reference/core/deck @@ -108,6 +113,7 @@ def __init__( self.description = description self.effects = effects self.map_provider = str(map_provider).lower() if map_provider else None + self.map_projection = map_projection self._tooltip = tooltip self._show_error = show_error diff --git a/bindings/pydeck/pydeck/bindings/map_styles.py b/bindings/pydeck/pydeck/bindings/map_styles.py index 806773afda4..8cf9f70faf6 100644 --- a/bindings/pydeck/pydeck/bindings/map_styles.py +++ b/bindings/pydeck/pydeck/bindings/map_styles.py @@ -23,11 +23,11 @@ GOOGLE_ROAD = "roadmap" styles = { - DARK: {"mapbox": MAPBOX_DARK, "carto": CARTO_DARK}, - DARK_NO_LABELS: {"carto": CARTO_DARK_NO_LABELS}, - LIGHT: {"mapbox": MAPBOX_LIGHT, "carto": CARTO_LIGHT}, - LIGHT_NO_LABELS: {"carto": CARTO_LIGHT_NO_LABELS}, - ROAD: {"carto": CARTO_ROAD, "google_maps": GOOGLE_ROAD, "mapbox": MAPBOX_ROAD}, + DARK: {"mapbox": MAPBOX_DARK, "carto": CARTO_DARK, "maplibre": CARTO_DARK}, + DARK_NO_LABELS: {"carto": CARTO_DARK_NO_LABELS, "maplibre": CARTO_DARK_NO_LABELS}, + LIGHT: {"mapbox": MAPBOX_LIGHT, "carto": CARTO_LIGHT, "maplibre": CARTO_LIGHT}, + LIGHT_NO_LABELS: {"carto": CARTO_LIGHT_NO_LABELS, "maplibre": CARTO_LIGHT_NO_LABELS}, + ROAD: {"carto": CARTO_ROAD, "google_maps": GOOGLE_ROAD, "mapbox": MAPBOX_ROAD, "maplibre": CARTO_ROAD}, SATELLITE: {"mapbox": MAPBOX_SATELLITE, "google_maps": GOOGLE_SATELLITE}, } @@ -35,6 +35,7 @@ BaseMapProvider.CARTO: DARK, BaseMapProvider.MAPBOX: DARK, BaseMapProvider.GOOGLE_MAPS: GOOGLE_ROAD, + BaseMapProvider.MAPLIBRE: DARK, } diff --git a/bindings/pydeck/pydeck/io/templates/index.j2 b/bindings/pydeck/pydeck/io/templates/index.j2 index e03ea3eb99e..fdd74bd01e0 100644 --- a/bindings/pydeck/pydeck/io/templates/index.j2 +++ b/bindings/pydeck/pydeck/io/templates/index.j2 @@ -10,6 +10,7 @@ {% endif %} + {{ deckgl_jupyter_widget_bundle }}