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

Add ecosystem/integrations documentation #350

Merged
merged 5 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/shiny-example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions docs/ecosystem/geoarrow.md
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.
23 changes: 23 additions & 0 deletions docs/ecosystem/geopandas.md
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)
```
5 changes: 5 additions & 0 deletions docs/ecosystem/index.md
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.
5 changes: 5 additions & 0 deletions docs/ecosystem/jupyter-widgets.md
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.
108 changes: 108 additions & 0 deletions docs/ecosystem/panel.md
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()
```
39 changes: 39 additions & 0 deletions docs/ecosystem/shiny.md
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()]
```
141 changes: 0 additions & 141 deletions examples/layers/bitmap-layer.ipynb

This file was deleted.

13 changes: 7 additions & 6 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,19 @@ nav:
- api/layers/arc-layer.md
- api/layers/text-layer.md
- api/experimental/traits.md
- Ecosystem:
- ecosystem/index.md
- ecosystem/geoarrow.md
- ecosystem/geopandas.md
- ecosystem/panel.md
- ecosystem/shiny.md

# - Caveats: caveats.md
- Performance: performance.md
- Changelog: CHANGELOG.md
- Alternatives: alternatives.md
- "How it works?": how-it-works.md

# - Ecosystem:
# - ecosystem/index.md
# - ecosystem/geopandas.md
# - ecosystem/geoarrow.md

watch:
- lonboard
- docs
Expand Down Expand Up @@ -121,7 +122,7 @@ plugins:
alias_type: "copy"
canonical_version: "latest"
- mkdocs-jupyter:
include_source: True
include_source: true
ignore: ["**/.ipynb_checkpoints/*.ipynb"]
- mkdocstrings:
enable_inventory: true
Expand Down
Loading