rtplot — real-time plotting over ZMQ
rtplot pushes live data from a Python script to a browser plot — locally or across a network — in a few lines of code. The plot page also hosts interactive widgets (buttons, sliders, dials, numeric / text displays) that feed values back to the sender in real time.
Typical use: a robot or data-acquisition script runs on a Raspberry Pi, and you watch signals and tweak gains from a laptop on the same Wi-Fi.
How it works
Two processes talking over ZMQ, plus a browser viewer:
flowchart TD
script["Your Python script<br/>send_array() · poll_controls()"]
subgraph server["rtplot-server"]
browser["browser tab<br/>localhost:8050"]
end
script -- "data :5555" --> server
server -- "controls :5556" --> script
Sender and server don't have to be on the same machine — see the networking guide.
Install
Server — grab the prebuilt binary from the Releases page:
| Platform | Asset |
|---|---|
| Windows | rtplot-server-<version>-windows-x64.exe |
| Linux | rtplot-server-<version>-linux-x86_64.tar.gz |
| macOS (Apple Silicon) | rtplot-server-<version>-macos-arm64.tar.gz |
No Python needed on the viewing machine. On Windows the binary opens a small Tk status window showing the listening URL.
Set columns per row in your sender's layout with
PlotRow([Plot(names=["a"]), Plot(names=["b"])], columns=2).
Start the server normally; each row can use a different column count.
See the multi-column example for typed and
dict forms, including a layout with two, one, and three columns.
Client — pip install in the env that runs your script:
pip install better-rtplot
(If you'd rather run the server from Python too, use
pip install "better-rtplot[browser]" — see the
API reference.)
Your first plot
flowchart TD
t1["terminal 1: start the server"]
t2["terminal 2: run your script"]
br["browser: open localhost:8050"]
t1 --> t2 --> br
Terminal 1 — start the server. Run the prebuilt rtplot-server
binary you downloaded above. Open http://localhost:8050 in a
browser — the page is blank until data arrives.
Terminal 2 — run your sender script. Save as my_plot.py:
from rtplot import client
import time
client.local_plot()
client.initialize_plots(["my signal"])
for i in range(1000):
client.send_array(i * 0.01)
time.sleep(0.01)
python my_plot.py
A rising line now draws itself in the browser tab.
Highlights
- Fast. Binary WebSocket deltas up to 1 kHz; the browser coalesces
samples into one repaint per
requestAnimationFrame, so rendering tracks your monitor refresh rate regardless of sample rate. - Browser-based. aiohttp + uPlot, no desktop GUI toolkit, works over SSH port forwarding.
- Remote-friendly. Sender or plot host can bind. Live Bind / Connect buttons retarget without restart.
- Config lives with the data. The sender declares plot layout.
- Responsive presentation. Native phone sizing, essential actions, compact navigation, and explicit semantic styles. See the presentation guide and before/after screenshots.
- Sections and runtime state. Optional collapsible sections, persistent status controls, and presentation updates that preserve streaming history. See the section API and workflow example.
- Interactive controls. Buttons, sliders, dials, displays — polled from your loop, no threads, no callbacks.
- LaTeX labels. Use
$...$or\(...\)in plot and control text; the server bundles KaTeX and works offline. - Static HTML snapshots.
save_snapshot("out.html")writes a self-contained file with the current trace and math rendering embedded.
Where to go next
- API reference — every
rtplot.clientfunction, the plot-layout schema, interactive controls, snapshots, browser UI, andrtplot-serverCLI flags. - Networking guide — Mode A vs. Mode B, viewing from a phone or second laptop, the WSL2 wrinkle, Cloudflare Tunnel, Tailscale.
- Examples — runnable scripts with embedded HTML snapshots you can open offline.
Issues and feature requests: github.com/jmontp/rtplot/issues.
Dropdown controls: API and examples.
Release files for better-rtplot 0.6.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| better_rtplot-0.6.1.tar.gz | 451.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| better_rtplot-0.6.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 909.4 kB
Release files / better_rtplot-0.6.1.tar.gz
| Download URL | better_rtplot-0.6.1.tar.gz |
|---|---|
| Size | 451.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d7cbe0c4474bdb9785e5d705ebc87aa2cf71ad847a31c1b9b61037847a929047
|
|
BLAKE2b-256 checksum How to use checksums |
c67cec2bbe566d455efb54735e11a3fc6e15a05a089f1810e2a55759df9a33b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / better_rtplot-0.6.1-py3-none-any.whl
| Download URL | better_rtplot-0.6.1-py3-none-any.whl |
|---|---|
| Size | 457.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0390a90d6dc62d45a4df1a54e5d65161b97471e86d2827e784d75f5a2e882aac
|
|
BLAKE2b-256 checksum How to use checksums |
bb9cbbab2a6b07c184caf44364297734aa3dd7bb9e4ba309101798b336ea5668
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|