-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ecosystem/integrations documentation (#350)
### Change list - Documentation for integrating with shiny, panel, geopandas, geoarrow-rust, jupyter widgets
- Loading branch information
1 parent
bf1794c
commit bf843c0
Showing
9 changed files
with
211 additions
and
147 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# GeoArrow | ||
|
||
[GeoArrow](https://geoarrow.org/) is an in-memory data structure for storing vector geospatial data and associated attributes. Lonboard uses GeoArrow internally and is the [primary reason why Lonboard is fast](../how-it-works.md#how-is-it-so-fast). | ||
|
||
There's a burgeoning ecosystem of Python libraries that use GeoArrow internally. Creating Lonboard `Layer` objects from GeoArrow tables is the fastest way to visualize data, as no conversions are needed on the Python side. | ||
|
||
## geoarrow-rust | ||
|
||
[geoarrow-rust](https://geoarrow.org/geoarrow-rs/python/latest/) is a Python library implementing the GeoArrow specification with efficient spatial operations. This library has "rust" in the name because it is implemented based on the [GeoArrow Rust implementation](https://geoarrow.org/geoarrow-rs/). | ||
|
||
```py | ||
from geoarrow.rust.core import GeoTable, read_geojson | ||
from lonboard import Map, PathLayer | ||
|
||
path = "/path/to/file.geojson" | ||
geo_table = read_geojson(path) | ||
|
||
# Assuming the GeoJSON contains LineString or MultiLineString data | ||
layer = PathLayer(table=geo_table) | ||
m = Map(layer) | ||
m | ||
``` | ||
|
||
Refer to the [geoarrow-rust](https://geoarrow.org/geoarrow-rs/python/latest/) documentation for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# GeoPandas | ||
|
||
[GeoPandas](https://geopandas.org/en/stable/) extends the Pandas data frame library to allow spatial operations on geospatial data. | ||
|
||
All relevant Lonboard layer classes have a [`from_geopandas`](../api/layers/base-layer.md#lonboard.BaseArrowLayer.from_geopandas) method for `GeoDataFrame` input. | ||
|
||
Some layer types, such as [`BitmapLayer`](../api/layers/bitmap-layer.md), don't have a `from_geopandas` method because the rendering isn't relevant to GeoPandas (i.e. GeoPandas doesn't store image data). | ||
|
||
## Example | ||
|
||
```py | ||
import geodatasets | ||
import geopandas as gpd | ||
from lonboard import Map, SolidPolygonLayer | ||
|
||
# New York City boroughs | ||
gdf = gpd.read_file(geodatasets.get_path('nybb')) | ||
layer = SolidPolygonLayer.from_geopandas( | ||
gdf, | ||
get_fill_color=[255, 0, 0], | ||
) | ||
m = Map(layer) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Ecosystem | ||
|
||
Lonboard aims to both integrate closely in the existing Python geospatial ecosystem and be future proof for the next generation of Python geospatial libraries. | ||
|
||
The pages in this section outline various integrations. If there's a library you think Lonboard should integrate with or you want to document existing compatibility, [create an issue](https://github.com/developmentseed/lonboard/issues/new) to discuss. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Jupyter Widgets | ||
|
||
[Jupyter Widgets](https://ipywidgets.readthedocs.io/en/stable/) are interactive browser controls for Jupyter notebooks. While Lonboard's classes are themselves widgets, Jupyter Widgets' design means that widgets integrate with other widgets seamlessly. | ||
|
||
For example, the `ipywidgets` Python library [includes many core widgets](https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20List.html) like sliders, dropdowns, color pickers, and file upload elements. Then you can [_link widgets together_](https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Events.html#linking-widgets). This means that your widget-based slider or chart can create events that change the display of a Lonboard map based on user input events. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Panel | ||
|
||
[Panel](https://panel.holoviz.org/) is a tool to build interactive web applications and dashboards using Python code. | ||
|
||
Panel [has been reported to work](https://github.com/developmentseed/lonboard/issues/262) with Lonboard. However, it appears that Panel [does not support reactive updates](https://github.com/holoviz/panel/issues/5921) in the same way that [Shiny](./shiny) does, so the map will necessarily be recreated from scratch on every update. | ||
|
||
## Example | ||
|
||
This example was written by [@MarcSkovMadsen](https://github.com/MarcSkovMadsen) in [issue #262](https://github.com/developmentseed/lonboard/issues/262). | ||
|
||
```py | ||
"""Panel data app based on https://developmentseed.org/lonboard/latest/examples/north-america-roads/""" | ||
# pip install panel colorcet ipywidgets_bokeh geopandas palettable lonboard | ||
import colorcet as cc | ||
import geopandas as gpd | ||
|
||
from lonboard import Map, PathLayer | ||
from lonboard.colormap import apply_continuous_cmap | ||
from palettable.palette import Palette | ||
|
||
import panel as pn | ||
|
||
url = "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_roads_north_america.zip" | ||
path = "ne_10m_roads_north_america.zip" | ||
|
||
try: | ||
gdf = pn.state.as_cached( | ||
"ne_10m_roads_north_america", gpd.read_file, filename=path, engine="pyogrio" | ||
) | ||
except: | ||
gdf = pn.state.as_cached( | ||
"ne_10m_roads_north_america", gpd.read_file, filename=url, engine="pyogrio" | ||
) | ||
|
||
state_options = sorted(state for state in gdf["state"].unique() if state) | ||
|
||
|
||
def to_rgb(hex: str) -> list: | ||
h = hex.strip("#") | ||
return list(int(h[i : i + 2], 16) for i in (0, 2, 4)) | ||
|
||
|
||
def to_palette(cmap) -> Palette: | ||
"""Returns the ColorCet colormap as a palettable Palette""" | ||
colors = [to_rgb(item) for item in cmap] | ||
return Palette(name="colorcet", map_type="colorcet", colors=colors) | ||
|
||
|
||
def create_map(state="California", cmap=cc.fire, alpha=0.8): | ||
palette = to_palette(cmap) | ||
data = gdf[gdf["state"] == state] | ||
layer = PathLayer.from_geopandas(data, width_min_pixels=0.8) | ||
normalized_scale_rank = (data["scalerank"] - 3) / 9 | ||
layer.get_color = apply_continuous_cmap(normalized_scale_rank, palette, alpha=alpha) | ||
map_ = Map(layers=[layer], _height=650) | ||
return map_ | ||
|
||
|
||
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 | ||
pn.extension("ipywidgets") | ||
state = pn.widgets.Select( | ||
value="California", | ||
options=state_options, | ||
width=150, | ||
name="State", | ||
sizing_mode="stretch_width", | ||
) | ||
cmap = pn.widgets.ColorMap( | ||
value=cc.fire, | ||
options=cc.palette, | ||
ncols=3, | ||
swatch_width=100, | ||
name="cmap by Colorcet", | ||
sizing_mode="stretch_width", | ||
) | ||
alpha = pn.widgets.FloatSlider( | ||
value=0.8, start=0, end=1, name="Alpha", min_width=100, sizing_mode="stretch_width" | ||
) | ||
logo = pn.pane.Image( | ||
"https://github.com/developmentseed/lonboard/raw/main/assets/dalle-lonboard.jpg" | ||
) | ||
def title(state): | ||
return f"# North America Roads: {state}" | ||
|
||
settings = pn.Column(state, cmap, alpha) | ||
description = pn.Column(pn.pane.Markdown(description, margin=5), logo) | ||
component = pn.Column( | ||
pn.bind(title, state=state), | ||
pn.panel( | ||
pn.bind(create_map, state=state, cmap=cmap, alpha=alpha.param.value_throttled), | ||
sizing_mode="stretch_both", | ||
), | ||
sizing_mode="stretch_both", | ||
) | ||
pn.template.FastListTemplate( | ||
logo="https://panel.holoviz.org/_static/logo_horizontal_dark_theme.png", | ||
title="Works with LonBoard", | ||
main=[component], | ||
sidebar=[description, settings], | ||
).servable() | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Shiny | ||
|
||
[Shiny](https://shiny.posit.co/py/) is a tool to build interactive web applications and dashboards using Python code. Shiny [integrates with Jupyter Widgets](https://shiny.posit.co/py/docs/jupyter-widgets.html), which means that Lonboard is supported out-of-the-box. | ||
|
||
Pay attention to the ["Efficient updates"](https://shiny.posit.co/py/docs/jupyter-widgets.html#efficient-updates) section of the Shiny documentation. This is the most efficient way to create a reactive map. Take care to not recreate the `Map` widget from scratch on updates, as that will send data from Python to the browser anew. | ||
|
||
|
||
## Example | ||
|
||
![](../assets/shiny-example.gif) | ||
|
||
```py | ||
import geopandas as gpd | ||
from shiny import reactive | ||
from shiny.express import input, ui | ||
from shinywidgets import render_widget | ||
|
||
from lonboard import Map, ScatterplotLayer | ||
|
||
colors = { | ||
"Red": [200, 0, 0], | ||
"Green": [0, 200, 0], | ||
"Blue": [0, 0, 200], | ||
} | ||
|
||
ui.input_select("color_select", "Color", choices=list(colors.keys())) | ||
|
||
|
||
@render_widget | ||
def map(): | ||
gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_cities")) | ||
layer = ScatterplotLayer.from_geopandas(gdf, radius_min_pixels=2) | ||
return Map(layer) | ||
|
||
|
||
@reactive.effect | ||
def set_fill_color(): | ||
map.widget.layers[0].get_fill_color = colors[input.color_select()] | ||
``` |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters