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 configuration

  • Real-time data streaming and chart updates

  • Custom scales and styling options

  • Legend display with viser.uplot.Legend

Source: examples/02_gui/09_uplot.py

uPlot integration

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)