uPlot integration¶
Embed lightweight, fast uPlot charts directly in the GUI interface.
This example demonstrates real-time data visualization using viser.GuiApi.add_uplot()
with multiple animated sine wave plots. uPlot provides efficient rendering for time-series data with smooth 60fps updates.
Features demonstrated:
Multiple synchronized plots with
viser.uplot.Series
configurationReal-time data streaming and chart updates
Custom scales and styling options
Legend display with
viser.uplot.Legend
Source: examples/02_gui/09_uplot.py

Code¶
1from __future__ import annotations
2
3import time
4
5import numpy as np
6import tyro
7
8import viser
9import viser.uplot
10
11
12def y(x: np.ndarray, offset: float) -> np.ndarray:
13 return np.sin(2 * np.pi * x + offset)
14
15
16def main(num_plots: int = 5, num_timesteps: int = 100, num_lines: int = 3) -> None:
17 server = viser.ViserServer()
18 time_step = 1.0 / 60.0
19
20 # Data for uPlot: tuple of arrays where first is x-data, rest are y-data.
21 x_data = time_step * np.arange(num_timesteps, dtype=np.float64)
22 data = (x_data, *[y(x_data, i) for i in range(num_lines)])
23 print("Data shapes:", [arr.shape for arr in data])
24
25 uplot_handles: list[viser.GuiUplotHandle] = []
26 for _ in range(num_plots):
27 uplot_handles.append(
28 server.gui.add_uplot(
29 data=data,
30 series=(
31 viser.uplot.Series(label="time"),
32 *[
33 viser.uplot.Series(
34 label=f"y{i}",
35 stroke=["red", "green", "blue"][i % 3],
36 width=2,
37 )
38 for i in range(num_lines)
39 ],
40 ),
41 scales={
42 "x": viser.uplot.Scale(
43 time=False,
44 auto=True,
45 ),
46 "y": viser.uplot.Scale(range=(-1.5, 2.5)),
47 },
48 legend=viser.uplot.Legend(show=True),
49 aspect=1.0,
50 )
51 )
52
53 while True:
54 # Update the line plot.
55 x_data = x_data + time_step
56 for uplot_handle in uplot_handles:
57 uplot_handle.data = (x_data, *[y(x_data, i) for i in range(num_lines)])
58 time.sleep(time_step)
59
60
61if __name__ == "__main__":
62 tyro.cli(main)