1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
r"""
Version for trame 1.x - https://github.com/Kitware/trame/blob/release-v1/examples/PlainPython/GeoMaps/MappingDemo/app.py
Delta v1..v2 - https://github.com/Kitware/trame/commit/c7aba7c09c4b0d29cf1e4015ae65f214f1828805
Installation requirements:
pip install trame trame-vuetify trame-vtk trame-deckgl
"""
import os
import pandas as pd
import pydeck as pdk
from trame.app import get_server
from trame.ui.vuetify import SinglePageLayout
from trame.widgets import deckgl, vuetify
# -----------------------------------------------------------------------------
# Trame setup
# -----------------------------------------------------------------------------
server = get_server(client_type="vue2")
state, ctrl = server.state, server.controller
# -----------------------------------------------------------------------------
# Getting a Mapbox API key
# -----------------------------------------------------------------------------
# By default, pydeck 0.6 provides basemap tiles through Carto.
#
# You can optionally use a Mapbox API key, by registering for Mapbox via
# this link [1]. You should then create a new public API token [2].
# You can learn more about Mapbox tokens via their documentation [3].
#
# [1] https://account.mapbox.com/auth/signup/
# [2] https://account.mapbox.com/access-tokens/
# [3] https://docs.mapbox.com/help/how-mapbox-works/access-tokens/#how-access-tokens-work
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Deck.gl / MapBox
# Expect MAPBOX_API_KEY environment variable
# -----------------------------------------------------------------------------
defaultLayers = [
"Bike Rentals",
"Bart Stop Exits",
"Bart Stop Names",
"Outbound Flow",
]
# -----------------------------------------------------------------------------
def from_data_file(filename):
url = (
"https://raw.githubusercontent.com/streamlit/"
"example-data/master/hello/v1/%s" % filename
)
return pd.read_json(url)
ALL_LAYERS = {
"Bike Rentals": pdk.Layer(
"HexagonLayer",
data=from_data_file("bike_rental_stats.json"),
get_position=["lon", "lat"],
radius=200,
elevation_scale=4,
elevation_range=[0, 1000],
extruded=True,
),
"Bart Stop Exits": pdk.Layer(
"ScatterplotLayer",
data=from_data_file("bart_stop_stats.json"),
get_position=["lon", "lat"],
get_color=[200, 30, 0, 160],
get_radius="[exits]",
radius_scale=0.05,
),
"Bart Stop Names": pdk.Layer(
"TextLayer",
data=from_data_file("bart_stop_stats.json"),
get_position=["lon", "lat"],
get_text="name",
get_color=[0, 0, 0, 200],
get_size=15,
get_alignment_baseline="'bottom'",
),
"Outbound Flow": pdk.Layer(
"ArcLayer",
data=from_data_file("bart_path_stats.json"),
get_source_position=["lon", "lat"],
get_target_position=["lon2", "lat2"],
get_source_color=[200, 30, 0, 160],
get_target_color=[200, 30, 0, 160],
auto_highlight=True,
width_scale=0.0001,
get_width="outbound",
width_min_pixels=3,
width_max_pixels=30,
),
}
# -----------------------------------------------------------------------------
# Callbacks
# -----------------------------------------------------------------------------
@state.change("activeLayers")
def update_map(activeLayers, **kwargs):
selected_layers = [
layer for layer_name, layer in ALL_LAYERS.items() if layer_name in activeLayers
]
if selected_layers:
deck = pdk.Deck(
map_provider="mapbox",
map_style="mapbox://styles/mapbox/light-v9",
initial_view_state={
"latitude": 37.76,
"longitude": -122.4,
"zoom": 11,
"pitch": 50,
},
layers=selected_layers,
)
ctrl.deck_update(deck)
else:
state.error = "Please choose at least one layer above."
# -----------------------------------------------------------------------------
# GUI Layout
# -----------------------------------------------------------------------------
state.trame__title = "Deck + Mapbox Demo"
with SinglePageLayout(server) as layout:
layout.title.set_text("Deck + Mapbox Demo")
with layout.content:
deckMap = deckgl.Deck(
mapbox_api_key=os.environ["MAPBOX_API_KEY"],
style="width: 100vw;",
classes="fill-height",
)
ctrl.deck_update = deckMap.update
vuetify.VSelect(
style="position: absolute; top: 10px; left: 25px; width: 600px;",
items=("layerNames", defaultLayers),
v_model=("activeLayers", defaultLayers),
dense=True,
hide_details=True,
multiple=True,
chips=True,
)
# -----------------------------------------------------------------------------
# Start server
# -----------------------------------------------------------------------------
if __name__ == "__main__":
server.start()
|