connect tripslayer to Panel #1118
-
|
Hi, I want to use a TripsLayer in a Panel "dashboard" instead of using the ipywidgets in jupyter. I tried to connect the TripsLayer to panel toggle button and update the current_time parameter of the tripslayer through a animation callback. Is also tried to just call the animate function from lonboard when the Panel butten is pushed. I unfortunately don´t get this to work. The trips show up in the map directly, instead of the dynamics trips that I expect. Has anyone tried this before and got it to work? Thanks for any feedback or tips! |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
|
I've never used Panel so I don't have any suggestions here. Somehow you need to be able to sequentially update the timestamp attribute on the layer for it to animate |
Beta Was this translation helpful? Give feedback.
-
|
thank for your response :-) ! Yes, I guess the issue is in updating the timestamp in the layer, because the animation widget just works fine (at least it counts when interacted with). Should the widget update the timestamp as timestamp type or ms (integer/float), or... ? |
Beta Was this translation helpful? Give feedback.
-
|
How did I miss this discussion? The trips layer's animate method won't work because it relies on ipywidgets jsdlink which doesnt work for panel apps. In panel we can use the Player widget along with a disabled datetimeinput widget bound to to the trips layer to achieve the same result in a panel app. I took the guts of the animate method and rewired it to use the panel components below. I haven't used this trips layer before, it's pretty neat, I've got some ideas how I could have some fun with it!
If you're using UV you can run this with # /// script
# requires-python = "==3.10"
# dependencies = [
# "arro3-core",
# "arro3-io",
# "arro3-compute",
# "panel",
# "ipykernel",
# "ipywidgets",
# "movingpandas",
# "ipywidgets_bokeh==1.5.0",
# "geopandas",
# "lonboard",
# "pyarrow",
# "requests",
# ]
# ///
from datetime import timedelta
from io import BytesIO
import panel as pn
import requests
from arro3.io import read_parquet
from lonboard import Map, TripsLayer
from lonboard._constants import MIN_INTEGER_FLOAT32
from lonboard._utils import timestamp_max_physical_value
pn.extension("ipywidgets")
url = "https://github.com/kylebarron/adsb-extract/releases/download/v0.1/2024-10-03_traces.parquet"
r = requests.get(url)
table = read_parquet(BytesIO(r.content)).read_all()
layer = TripsLayer(
table=table,
get_timestamps=table["timestamp"],
width_min_pixels=2,
get_color=[30, 30, 200, 200],
trail_length=200,
# Turn off tooltip data selection for better performance
pickable=False,
)
m = Map(
layer,
view_state={
"longitude": -73.8,
"latitude": 40.6,
"zoom": 9.5,
"pitch": 50.6,
"bearing": 8.24,
},
height=800,
)
def panel_animate(
layer: TripsLayer,
step: timedelta,
fps: float = 50,
) -> pn.Row:
interval = 1000 / fps
time_unit = layer.get_timestamps.type.value_type.time_unit
# Convert the `step` into the units used by the timestamps on the layer.
if time_unit == "s":
resolved_step = step.total_seconds()
elif time_unit == "ms":
resolved_step = step.total_seconds() * 1000
elif time_unit == "us":
resolved_step = step.total_seconds() * 1000**2
elif time_unit == "ns":
resolved_step = step.total_seconds() * 1000**3
max_value = timestamp_max_physical_value(layer.get_timestamps)
play_w = pn.widgets.Player(
value=MIN_INTEGER_FLOAT32,
start=MIN_INTEGER_FLOAT32,
end=max_value,
step=int(resolved_step),
interval=int(interval),
loop_policy="loop",
show_value=False,
)
datetime_w = pn.widgets.DatetimeInput(name='Date/Time', disabled=True)
def on_player_update(value):
layer._current_time = value
datetime_w.value=layer._current_time_to_datetime(value)
pn.bind(on_player_update, play_w, watch=True)
return pn.Row(play_w, datetime_w)
animation_controls = panel_animate(layer, timedelta(minutes=1))
app = pn.Column(
"# Lonboard trips layer in a panel app :)",
pn.pane.IPyWidget(m, height=500, width=1000),
animation_controls,
)
# Enable dual-mode execution
if pn.state.served:
# Served mode: `panel serve script.py`
app.servable(title="hello")
elif __name__ == "__main__":
# Script mode: `python script.py`
app.show(port=5007) |
Beta Was this translation helpful? Give feedback.

How did I miss this discussion? The trips layer's animate method won't work because it relies on ipywidgets jsdlink which doesnt work for panel apps. In panel we can use the Player widget along with a disabled datetimeinput widget bound to to the trips layer to achieve the same result in a panel app.
I took the guts of the animate method and rewired it to use the panel components below. I haven't used this trips layer before, it's pretty neat, I've got some ideas how I could have some fun with it!
If you're using UV you can run this with
uv run panel_trip.py