holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.76k stars 517 forks source link

Make IpyWidgets allow_refs like other panes #5921

Open MarcSkovMadsen opened 11 months ago

MarcSkovMadsen commented 11 months ago

I would like to demonstrate that Panel works with AnyWidget and now lonboard. I would like to show the integration via pn.bind.

But it seems I cannot use a bound function with pn.pane.IpyWidgets because the object of pn.pane.IpyWidget has allow_refs=False. Other panes have this setting to True. Why not IpyWidgets?`

Works - but not dynamic


# pip install panel ipywidgets_bokeh geopandas palettable lonboard
import geopandas as gpd
import palettable.colorbrewer.diverging

from lonboard import Map, PathLayer
from lonboard.colormap import apply_continuous_cmap
import panel as pn

url = 'https://naciscdn.org/naturalearth/10m/cultural/ne_10m_roads_north_america.zip'
path = "ne_10m_roads_north_america.zip"

gdf = pn.state.as_cached("ne_10m_roads_north_america", gpd.read_file, filename=path, engine="pyogrio")
state_options = sorted(state for state in gdf["state"].unique() if state)

def create_map(state="California"):
    data = gdf[gdf["state"] == state]
    normalized_scale_rank = (data['scalerank'] - 3) / 9

    layer = PathLayer.from_geopandas(data, width_min_pixels=0.8)
    layer.get_color = apply_continuous_cmap(normalized_scale_rank, palettable.colorbrewer.diverging.PuOr_10, alpha=0.8)
    map_ = Map(layers=[layer])
    return map_
# layer.get_color = apply_continuous_cmap(normalized_scale_rank, palettable.colorbrewer.diverging.PuOr_10, alpha=0.8)

description = """# lonboard

A Python library for **fast, interactive geospatial vector data visualization** in Jupyter (and Panel).

By utilizing new technologies like `GeoArrow` and `GeoParquet` in conjunction with GPU-based map rendering, lonboard aims to enable visualizing large geospatial datasets interactively through a simple interface.
"""

# THE PANEL APP

import panel as pn

pn.extension("ipywidgets")
state = pn.widgets.Select(value="California", options=state_options, name="State")
component = pn.Column(
    state,
    pn.pane.IPyWidget(create_map(), sizing_mode="stretch_both"),
    sizing_mode="stretch_both",
)
logo = pn.pane.Image("https://github.com/developmentseed/lonboard/raw/main/assets/dalle-lonboard.jpg")
pn.template.FastListTemplate(
    logo="https://panel.holoviz.org/_static/logo_horizontal_dark_theme.png",
    title="Works with LonBoard",
    main=[component], sidebar=[description, logo]
).servable()

image

Does not work

If I change line 41 to a bound function it does not work.

image

philippjfr commented 11 months ago

The problem here is that an IPywidget with a value traitlet is itself a valid reference and would be resolved. What is needed is finer grained control at the param level as to what kind of references should be allowed.

rsignell commented 9 months ago

@ahuang11 I don't know if something you could address, but I know the Pangeo community would love to have lonboard be dynamic and performant in Panel!

From https://github.com/developmentseed/lonboard/issues/262#issuecomment-1826859977

When you select a new colormap, alpha, anything... the map element fully reloads... that's pretty bad. In particular, that seems really bad because all the map data will be re-parsed and re-rendered from scratch (and maybe even re-downloaded?). lonboard's architecture assumes that you have a stateful jupyter widget on the JS side, and so changing a colormap or the alpha should not create a new map.

philippjfr commented 9 months ago

That seems like incorrect usage of Panel and lonboard more than an issue with either library. I'm out for the next few days but can try to build a new example.

philippjfr commented 9 months ago

Reactive updates like we support for Panel cannot be supported in ipywidgets unless we somehow upstream support for that, so writing callback based code is the only approach that will work.

rsignell commented 9 months ago

@philippjfr a new example from a GURU would be great! 😸

philippjfr commented 9 months ago

Just read the original request here again, even if we did support the original request that wouldn't result in efficient updates so I almost think we shouldn't support dynamic references so folks don't attempt this approach and then complain that Panel is inefficient.