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/08_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                title="Real-time Sine Waves",
42                scales={
43                    "x": viser.uplot.Scale(
44                        time=False,
45                        auto=True,
46                    ),
47                    "y": viser.uplot.Scale(range=(-1.5, 2.5)),
48                },
49                legend=viser.uplot.Legend(show=True),
50                aspect=2.0,
51            )
52        )
53
54    while True:
55        # Update the line plot.
56        x_data = x_data + time_step
57        for uplot_handle in uplot_handles:
58            uplot_handle.data = (x_data, *[y(x_data, i) for i in range(num_lines)])
59        time.sleep(time_step)
60
61
62if __name__ == "__main__":
63    tyro.cli(main)