MarcSkovMadsen commited on
Commit
c32e2b7
1 Parent(s): 6ed5a12

Improve efficiency with in-place updates

Browse files
Files changed (1) hide show
  1. app.py +97 -71
app.py CHANGED
@@ -1,98 +1,124 @@
1
- """
2
- Checkout https://awesome-panel.org/resources/lonboard_dashboard/
3
- """
4
- # pip install panel colorcet ipywidgets_bokeh geopandas palettable lonboard
5
  import colorcet as cc
6
  import geopandas as gpd
 
7
 
8
  from lonboard import Map, PathLayer
9
  from lonboard.colormap import apply_continuous_cmap
 
10
  from palettable.palette import Palette
11
 
12
  import panel as pn
13
 
 
 
14
  url = "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_roads_north_america.zip"
15
- path = "ne_10m_roads_north_america.zip"
16
 
17
- try:
18
- gdf = pn.state.as_cached(
19
- "ne_10m_roads_north_america", gpd.read_file, filename=path, engine="pyogrio"
20
- )
21
- except:
22
- gdf = pn.state.as_cached(
23
- "ne_10m_roads_north_america", gpd.read_file, filename=url, engine="pyogrio"
24
- )
25
 
 
26
  state_options = sorted(state for state in gdf["state"].unique() if state)
27
 
 
 
 
 
 
 
 
 
 
28
 
29
  def to_rgb(hex: str) -> list:
30
  h = hex.strip("#")
31
  return list(int(h[i : i + 2], 16) for i in (0, 2, 4))
32
 
33
-
34
  def to_palette(cmap) -> Palette:
35
  """Returns the ColorCet colormap as a palettable Palette"""
36
  colors = [to_rgb(item) for item in cmap]
37
  return Palette(name="colorcet", map_type="colorcet", colors=colors)
38
 
39
-
40
- def create_map(state="California", cmap=cc.fire, alpha=0.8):
41
- palette = to_palette(cmap)
42
- data = gdf[gdf["state"] == state]
43
- layer = PathLayer.from_geopandas(data, width_min_pixels=0.8)
44
- normalized_scale_rank = (data["scalerank"] - 3) / 9
45
- layer.get_color = apply_continuous_cmap(normalized_scale_rank, palette, alpha=alpha)
46
- map_ = Map(layers=[layer], _height=650)
47
- return map_
48
-
49
-
50
- description = """# lonboard
51
-
52
- A Python library for **fast, interactive geospatial vector data visualization** in Jupyter (and Panel).
53
-
54
- 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."""
55
-
56
-
57
- # THE PANEL APP
58
- pn.extension("ipywidgets")
59
- state = pn.widgets.Select(
60
- value="California",
61
- options=state_options,
62
- width=150,
63
- name="State",
64
- sizing_mode="stretch_width",
65
- )
66
- cmap = pn.widgets.ColorMap(
67
- value=cc.fire,
68
- options=cc.palette,
69
- ncols=3,
70
- swatch_width=100,
71
- name="cmap by Colorcet",
72
- sizing_mode="stretch_width",
73
- )
74
- alpha = pn.widgets.FloatSlider(
75
- value=0.8, start=0, end=1, name="Alpha", min_width=100, sizing_mode="stretch_width"
76
- )
77
- logo = pn.pane.Image(
78
- "https://github.com/developmentseed/lonboard/raw/main/assets/dalle-lonboard.jpg"
79
- )
80
- def title(state):
81
- return f"# North America Roads: {state}"
82
-
83
- settings = pn.Column(state, cmap, alpha)
84
- description = pn.Column(pn.pane.Markdown(description, margin=5), logo)
85
- component = pn.Column(
86
- pn.bind(title, state=state),
87
- pn.panel(
88
- pn.bind(create_map, state=state, cmap=cmap, alpha=alpha.param.value_throttled),
89
- sizing_mode="stretch_both",
90
- ),
91
- sizing_mode="stretch_both",
92
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  pn.template.FastListTemplate(
94
  logo="https://panel.holoviz.org/_static/logo_horizontal_dark_theme.png",
95
- title="Works with LonBoard",
96
- main=[component],
97
- sidebar=[description, settings],
 
98
  ).servable()
 
 
 
 
 
1
  import colorcet as cc
2
  import geopandas as gpd
3
+ import param
4
 
5
  from lonboard import Map, PathLayer
6
  from lonboard.colormap import apply_continuous_cmap
7
+ from lonboard._viewport import compute_view
8
  from palettable.palette import Palette
9
 
10
  import panel as pn
11
 
12
+ pn.extension("ipywidgets")
13
+
14
  url = "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_roads_north_america.zip"
 
15
 
16
+ @pn.cache
17
+ def get_data():
18
+ return gpd.read_file(filename=url, engine="pyogrio")
 
 
 
 
 
19
 
20
+ gdf = get_data()
21
  state_options = sorted(state for state in gdf["state"].unique() if state)
22
 
23
+ description = """# Lonboard
24
+
25
+ A Python library for **fast, interactive geospatial vector data visualization** in Jupyter (and Panel).
26
+
27
+ 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."""
28
+
29
+ logo = pn.pane.Image(
30
+ "https://github.com/developmentseed/lonboard/raw/main/assets/dalle-lonboard.jpg"
31
+ )
32
 
33
  def to_rgb(hex: str) -> list:
34
  h = hex.strip("#")
35
  return list(int(h[i : i + 2], 16) for i in (0, 2, 4))
36
 
 
37
  def to_palette(cmap) -> Palette:
38
  """Returns the ColorCet colormap as a palettable Palette"""
39
  colors = [to_rgb(item) for item in cmap]
40
  return Palette(name="colorcet", map_type="colorcet", colors=colors)
41
 
42
+ class StateViewer(pn.viewable.Viewer):
43
+ value: Map = param.ClassSelector(class_=Map, doc="The map object", constant=True)
44
+ state: str = param.Selector(default="California", objects=state_options)
45
+ cmap: str = param.Selector(default=cc.fire, objects=cc.palette, label="cmap by Colorcet")
46
+ alpha: float = param.Number(default=0.8, bounds=(0, 1))
47
+
48
+ data = param.DataFrame()
49
+
50
+ def __init__(self, **params):
51
+ params["value"] = params.get("value", Map(layers=[], view_state={"longitude": -119.81446785010868, "latitude": 36.08305565437565, "zoom": 5}))
52
+
53
+ super().__init__(**params)
54
+
55
+ self.value.layout.width=self.value.layout.height="100%"
56
+
57
+ self.description = pn.Column(pn.pane.Markdown(description, margin=5), logo)
58
+ self.settings = pn.Column(
59
+ pn.widgets.Select.from_param(self.param.state, sizing_mode="stretch_width"),
60
+ pn.widgets.ColorMap.from_param(
61
+ self.param.cmap,
62
+ ncols=3,
63
+ swatch_width=100,
64
+ name="cmap by Colorcet",
65
+ sizing_mode="stretch_width",
66
+ ),
67
+ pn.widgets.FloatSlider.from_param(
68
+ self.param.alpha, sizing_mode="stretch_width"
69
+ ),
70
+ margin=5,
71
+ sizing_mode="fixed",
72
+ width=300,
73
+ )
74
+ self.view = pn.Column(
75
+ self._title, pn.pane.IPyWidget(self.value, sizing_mode="stretch_both")
76
+ )
77
+ self._layout = pn.Row(
78
+ pn.Column(self.settings, sizing_mode="fixed", width=300),
79
+ self.view,
80
+ sizing_mode="stretch_both",
81
+ )
82
+
83
+ def __panel__(self):
84
+ return self._layout
85
+
86
+ @param.depends("state", watch=True, on_init=True)
87
+ def _update_data(self):
88
+ self.data = gdf[gdf["state"] == self.state]
89
+
90
+ def _get_color(self):
91
+ palette = to_palette(self.cmap)
92
+ normalized_scale_rank = (self.data["scalerank"] - 3) / 9
93
+ return apply_continuous_cmap(normalized_scale_rank, palette, alpha=self.alpha)
94
+
95
+ @param.depends("data", watch=True)
96
+ def _update_value(self):
97
+ layer = PathLayer.from_geopandas(self.data, width_min_pixels=0.8)
98
+ layer.get_color = self._get_color()
99
+ self.value.layers = [layer]
100
+ self._fly_to_center()
101
+
102
+ def _fly_to_center(self):
103
+ computed_view_state = compute_view(self.value.layers)
104
+ self.value.fly_to(
105
+ **computed_view_state,
106
+ duration=1000,
107
+ )
108
+
109
+ @param.depends("cmap", "alpha", watch=True)
110
+ def _update_layer_get_color(self):
111
+ self.value.layers[0].get_color = self._get_color()
112
+
113
+ @param.depends("state")
114
+ def _title(self):
115
+ return f"# North America Roads: {self.state}"
116
+
117
+ viewer = StateViewer()
118
  pn.template.FastListTemplate(
119
  logo="https://panel.holoviz.org/_static/logo_horizontal_dark_theme.png",
120
+ title="Works with Lonboard",
121
+ sidebar=[viewer.description, viewer.settings],
122
+ main=[viewer.view],
123
+ main_layout=None,
124
  ).servable()