Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issues rendering maplibre pydeck layers #833

Closed
cboettig opened this issue Jul 16, 2024 · 9 comments
Closed

issues rendering maplibre pydeck layers #833

cboettig opened this issue Jul 16, 2024 · 9 comments
Labels
bug Something isn't working

Comments

@cboettig
Copy link

Environment Information

  • leafmap version: 0.35.9
  • Python version: 3.10.12
  • Operating System: Ubuntu Linux, 22.04

Description

This minimal pure-pydeck example (based on pydeck docs) works:

import pydeck as pdk
layer = pdk.Layer(
        "H3HexagonLayer",
        'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf.h3cells.json',
        get_hexagon="hex",
    )

pdk.Deck(map_provider='carto', 
    map_style='light',
    initial_view_state=pdk.ViewState(
        latitude=37.74, longitude=-122.4, zoom=11, height=400
    ),
    layers=[layer],
)

But I try translating this to leafmap:

import leafmap.maplibregl as leafmap

m = leafmap.Map(style="positron",  center=(-122.4, 37.74), zoom=11,)
deck_grid_layer = {
    "@@type": "H3HexagonLayer",
    "id": "my-layer",
    "data": 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf.h3cells.json',
    "getHexagon": "@@=hex",
}

m.add_deck_layers([deck_grid_layer])
m

The map renders but the data layer isn't drawn.

I have noticed that pydeck/deck-gl is very sensitive to types, for instance, a slightly modified version of the pydeck code will fail in the same silent way (map but no data layer) because elevation_scale is given as a string instead of a numeric:

import pydeck as pdk
layer = pdk.Layer(
        "H3HexagonLayer",
        'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf.h3cells.json',
        get_hexagon="hex",
        extruded=True,
        get_elevation="count",
        elevation_scale="20",
    )

pdk.Deck(map_provider='carto', 
    map_style='light',
    initial_view_state=pdk.ViewState(
        latitude=37.74, longitude=-122.4, zoom=11, height=400
    ),
    layers=[layer],
)

I can confirm the example in the leafmap tutorial works for me though.

m = leafmap.Map(
    style="positron",
    center=(-122.4, 37.74),
    zoom=12,
    pitch=40,
)
deck_grid_layer = {
    "@@type": "GridLayer",
    "id": "GridLayer",
    "data": "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf-bike-parking.json",
    "extruded": True,
    "getPosition": "@@=COORDINATES",
    "getColorWeight": "@@=SPACES",
    "getElevationWeight": "@@=SPACES",
    "elevationScale": 4,
    "cellSize": 200,
    "pickable": True,
}

m.add_deck_layers([deck_grid_layer], tooltip="Number of points: {{ count }}")
m

I did notice it no longer works if data is given as a local geojson file or as a pandas data.frame, though pydeck supports those options, but I guess that makes sense since I gather leafmap maplibre doesn't use pydeck but goes to deck.gl via libremap bindings instead. So I've used URLs in my example above, but no luck.

From what I understand, @@= is just required on the 'getter' methods, get*.

@cboettig cboettig added the bug Something isn't working label Jul 16, 2024
@cboettig
Copy link
Author

one more footnote, trying some other types like scatterplot things seem to work as expected. (again based on pydeck examples

import leafmap.maplibregl as leafmap
m = leafmap.Map(style="positron", center=(-122.4, 37.74), zoom=12, pitch=40)

deck_grid_layer = {
    "@@type": "ScatterplotLayer",
    "id": "ScatterplotLayer",
    "data": "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-stations.json",
    "getPosition": "@@=coordinates",
    "getRadius": 200,
    "getFillColor": [255, 140, 0],
    "pickable": True,
}

m.add_deck_layers([deck_grid_layer])
m

@giswqs
Copy link
Member

giswqs commented Jul 16, 2024

This may be an issue with the upstream py-maplibre package. The developer console says the H3HexagonLayer class is not registered. I am not sure if pymaplibre supports all deckGL layer types or just a subset of them.

image

@giswqs
Copy link
Member

giswqs commented Jul 16, 2024

This is an example using py-maplibre directly without leafmap. Got the same error that the H3HexagonLayer class is not registered.

from maplibre import MapOptions
from maplibre.basemaps import Carto
from maplibre.controls import NavigationControl
from maplibre.ipywidget import MapWidget as Map

m = Map(
    MapOptions(
        style=Carto.POSITRON,
        center=(-122.4, 37.74),
        zoom=12,
        hash=True,
        pitch=40,
    )
)
m.add_control(NavigationControl())

deck_grid_layer = {
    "@@type": "H3HexagonLayer",
    "id": "my-layer",
    "data": 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf.h3cells.json',
    "getHexagon": "@@=hex",
}

m.add_deck_layers([deck_grid_layer], tooltip="Number of points: {{ count }}")
m

@giswqs
Copy link
Member

giswqs commented Jul 16, 2024

Closing this one as it is an upstream issue reported at eoda-dev/py-maplibregl#99.

@giswqs giswqs closed this as completed Jul 20, 2024
@cboettig
Copy link
Author

@giswqs This issue is now fixed upstream. Additionally, upstream, this works when data is a geopandas object rather than a URL, which is useful in some cases! However, in leafmap, this still only works when this is a URL for me. Lemme know if it would be better to open a new issue for this?

@giswqs
Copy link
Member

giswqs commented Aug 29, 2024

Awesome! PR is welcome

@cboettig
Copy link
Author

Thanks @giswqs ! I'll take a go at this!

@cboettig
Copy link
Author

@giswqs as usual the problem was between screen and keyboard. After the upstream fixes (and maybe even before?) we can pass pydeck layer directly, instead of the funky @@= syntax with the dict.

This means I can just paste the standard/already working pydeck layer directly into leafmap and viola!

import leafmap.maplibregl as leafmap
import pandas as pd
import pydeck as pdk

url = "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf.h3cells.json"
h3cells = pd.read_json(url, orient='records')

m = leafmap.Map(style="positron", center=(-122.4, 37.74), zoom=10, pitch=30)
layer = pdk.Layer(
        "H3HexagonLayer",
        h3cells,
        get_hexagon="hex",
        get_fill_color="[255 - count, 255, count]",
        extruded=True,
        get_elevation="count",
        elevation_scale=20,
    )
    
# leafmap's maplibre engine just renders the pydeck layer magically:    
m.add_deck_layers([layer])
m

This is so very nice!

@giswqs
Copy link
Member

giswqs commented Aug 29, 2024

Wow, that's great to know! Much more pythonic now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants