Visualization Tools¶
A live browser view, and self-contained HTML files you can keep.
Everything is dependency-free: figures are SVG built from strings, pages inline their own CSS. No matplotlib (slow to import in a request path), no Plotly bundle (3 MB of JavaScript per file), no CDN — a plot that renders blank because a CDN was unreachable is worse than no plot, and a clinical machine may have no internet at all.
start_monitor¶
Open a live browser view of a running session.
| Arg | Default | Meaning |
|---|---|---|
window_sec |
5.0 |
Seconds shown at once; adjustable in the page |
refresh_ms |
500 |
Redraw interval |
port |
0 |
Loopback port; 0 lets the OS pick a free one |
allow_control |
true |
Render the transport buttons and enable the control endpoint |
{
"url": "http://127.0.0.1:54812/?t=3Jk9_pQz...",
"port": 54812,
"bound_to": "127.0.0.1",
"allow_control": true,
"controls": ["play/pause", "restart", "skip -10s/+10s", "speed", "stop",
"mark event", "save report", "save traces", "save spectrum"]
}
The page shows:
- Rolling traces, each channel autoscaled to its own amplitude, with the per-channel peak in µV printed beside it. Per-channel scaling is what keeps a montage readable when one electrode has ten times its neighbour's amplitude.
- Event markers — dashed for markers and annotations, solid red for stimulation.
- Live relative band power and the dominant band.
- A per-electrode quality table updating as you watch.
- A filtered/raw toggle, so you can see what the chain is actually doing.
- Replay position when the session is a replay.
Driving the session from the page¶
With allow_control (the default) the page carries a control bar, so an
operator watching the screen does not have to go back to the agent for every
action:
| Control | Action | Applies to |
|---|---|---|
| ⏮ Restart | Seek to 0 and resume | Replay only |
| ⏯ Pause / Resume | Hold or continue the media clock | Replay only |
| −10s / +10s | Skip relative | Replay only |
| Scrub bar | Seek to any position | Replay only |
| Speed | 0.25× … 8× | Replay only |
| ⏹ Stop | Halt acquisition, release the device | Any session |
| 🔖 Mark | Log an event with the typed label | Any session |
| 💾 Report / Traces / Spectrum | Write a standalone HTML file | Any session |
| 🗑 Events | Clear the event log | Any session |
Keyboard: Space play/pause, ←/→ skip 10 s, M mark.
Replay-only controls are disabled on a live board, and everything is disabled once the session is stopped. Save buttons disable when nothing is buffered.
Stop keeps the data
The Stop button halts the producer and releases the device but leaves the
session in the store, so buffered signal can still be reviewed and saved.
That is deliberately different from the stop_stream tool, which drops the
session entirely.
One caveat worth knowing: seeking discards buffered signal (necessary so no window straddles the discontinuity). Seek and then immediately Stop and there is nothing left to save — the error says so explicitly rather than telling you to wait for a buffer that will never refill.
Read-only mode¶
Renders no buttons, and the control endpoint refuses even a correctly authenticated request. Use it when the screen is visible to someone who should watch but not touch.
Loopback only, token-gated
Binds to 127.0.0.1 and requires the random per-monitor token in the URL,
so it is not reachable from the network and cannot be read by guessing the
port. It is not encrypted and is not an authentication system — never
expose it through a tunnel, reverse proxy, or port forward.
Because the page can now stop a recording, control requests carry an extra
guard: they must be POST with an application/json content type, which
forces a CORS preflight this server never answers. A hostile local page
therefore cannot drive the session even if it guessed the port and token.
The page also carries a strict CSP and loads nothing external.
Only one monitor runs per session; starting again replaces it. stop_stream
tears it down automatically.
stop_monitor / list_monitors¶
stop_monitor(session_id) closes a monitor and frees its port.
list_monitors() returns active monitors with their URLs.
plot_stream¶
Render the recent signal as a standalone HTML file — a frozen snapshot, unlike
start_monitor.
| Arg | Default | Meaning |
|---|---|---|
seconds |
10.0 |
Signal to draw |
channels |
None |
Subset by name |
filtered |
true |
Draw the filtered signal |
show_events |
true |
Overlay event markers |
Returns: path to the written file, plus what it contains. Files go to
$EEG_MCP_HOME/plots/ with a timestamped name.
plot_spectrum¶
PSD and band composition as a standalone HTML file.
| Arg | Default | Meaning |
|---|---|---|
seconds |
8.0 |
Window; longer gives finer resolution |
channels |
None |
Subset by name |
fmax |
60.0 |
Highest frequency drawn |
Contains a log-power spectrum with the classical bands shaded behind it, a stacked relative-band-power bar per channel, and a peak-frequency table.
Returns: path, peak_freq per channel, dominant_band.
export_report¶
The one artefact to keep from a session.
| Arg | Default | Meaning |
|---|---|---|
seconds |
10.0 |
Window for traces and spectrum |
include_spectrum |
true |
Add PSD and band-power sections |
notes |
None |
Free text recorded at the top |
Sections: stat tiles (channels, rate, dominant band, flagged channels, event count) → traces with event markers → spectrum and band bars → per-channel quality table with faults called out → the full event log.
Returns: path, n_events, bad_channels, dominant_band, sections.
Typically ~120 KB. The test suite asserts self-containment by scanning output for any external URL, and validates that every SVG parses and every plotted point sits inside its viewBox — which is what catches a scaling regression that would silently push traces out of view.
Reports carry a research-use disclaimer. They are not diagnostic documents.
Choosing between them¶
| Want | Use |
|---|---|
| Watch it happen | start_monitor |
| Keep a picture of this moment | plot_stream |
| Look at the frequency content | plot_spectrum |
| One file for the record | export_report |
| Numbers, not pictures | read_window, get_band_power, get_psd |