Skip to content

examples: two demos for the 2.4.0 multi-panel viewer features - #20

Merged
RaulSimpetru merged 1 commit into
mainfrom
docs/multi-panel-examples
Jul 25, 2026
Merged

examples: two demos for the 2.4.0 multi-panel viewer features#20
RaulSimpetru merged 1 commit into
mainfrom
docs/multi-panel-examples

Conversation

@RaulSimpetru

Copy link
Copy Markdown
Member

channel_grid_demo.py already covers one viewer picking channels out of a multi-grid stream.
These cover the two arrangements 2.4.0 made possible, and each is built around the parameter that
makes it work.

examples/synthetic/multi_panel_grids.py — a panel per electrode grid. Five 64-channel arrays
of one 320-channel stream, each its own SignalViewer in a Grid(2, 3) cell.

  • widget_id keeps the five states apart — without it every SignalViewer("emg") resolves to one
    state and the tiles render identically.
  • channel_scope is the hard restriction: All selects 64, not 320; the count reads 64/64;
    [Edit…] lists only that array; shift-click and rubber-band drags stay inside it.
  • It passes initial_channels alongside the scope, because scope alone would open each panel on
    its array's first 16 channels (the >32 default policy, applied within the scope).
  • The docstring is explicit that the tiles do not share a y-scale, so amplitudes are not
    comparable across them by eye.

examples/synthetic/electrode_overview.py — the same five arrays as live spatial RMS maps
plus a detail viewer, built on Heatmap.ui(vrange=…).

  • All five maps get one colour range, recomputed each frame across all 320 channels. That is
    the load-bearing detail: with per-map autoscaling a silent array renders exactly like a busy one.
  • The source runs each array at a different amplitude and kills one contact on IN3, so the maps
    have something to reveal (verified: per-array mean RMS 0.99 → 0.15, dead contact 0.0).
  • Why maps rather than traces is stated up front: 64 overlaid traces in a small tile is texture,
    not signal; a map answers "which electrode is dead?" at a glance.

Both reuse the wall-clock-paced synthetic-source pattern from channel_grid_demo.py, so the
free-spinning acquire thread doesn't busy-loop generating data faster than fs.

Examples only — no library changes, no test changes.

channel_grid_demo.py already covers one viewer picking channels out of a
multi-grid stream. These cover the arrangements 2.4.0 made possible:

multi_panel_grids.py — a panel per electrode grid. Five 64-channel arrays of
one 320-channel stream, each its own SignalViewer in a Grid(2, 3) cell, showing
why both parameters are needed: widget_id keeps the five states apart (without
it they resolve to one and render identically), and channel_scope is the hard
restriction, so All/Invert, the N/total count, [Edit…] and shift-click all stay
inside that panel's array. It passes initial_channels alongside the scope,
since scope alone would open each panel on its array's first 16 channels.

electrode_overview.py — the same five arrays as live spatial RMS maps plus a
detail viewer, built on Heatmap's new vrange. All five share ONE colour range
recomputed across all 320 channels, which is what makes them comparable; with
per-map autoscaling a silent array renders exactly like a busy one. The source
runs each array at a different amplitude and kills one contact on IN3, so the
maps have something to reveal.

Both use the wall-clock-paced synthetic source pattern from channel_grid_demo,
so the acquire thread doesn't busy-loop generating data faster than fs.
@RaulSimpetru
RaulSimpetru merged commit d006ad0 into main Jul 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant