fix: persistence is the trace's own phosphor, not a density behind a stroke

The plotter now deposits every acquisition -- the newest included -- into one grid per trace and
draws no solid trace over it, each grid in that trace's colour and with a one-sweep ceiling (its own
commit, **1b8b55d**). This side needed almost no change of its own, because the colour was already
the trace's and the trace's colour is `RowSet::signal_color()` -- the invariants' one route -- but the
figures it reads back are now per trace:

- **The ceiling is left at the library's default of one sweep**, no longer derived from the fade.
  Deriving it from the steady state is the gain offset the user reported between the latest
  acquisition and the persistent image; a signal crossing the same place every acquisition now settles
  at the trace's colour, at full strength, and the newest sweep reads as the trace it is a picture of.
- **`cells`/`grid_bytes` are the sum over the row's traces** -- one grid each, a trace with no series
  holding none -- and both the probe and the exit dump carry `traces=` beside `rows=`. That is what
  makes the per-signal memory figure read: **556 537 cells and 2.2 MB per signal**, at 8904600 bytes
  over the four one-signal rows of the probe's run.

The probes, re-read on this build (the `verification.md` command, `--rate 500000 --batch 1000`):

    [density-probe] off enabled=0 ... rows=0 traces=0 cells=0 ink=0.0 peak=0.0000
    [density-probe] on enabled=1 ... rows=4 traces=4 cells=2226150 ink=226786.0 peak=1.0000
    [density-probe] step-acquisitions ... peak=1.5000
    [density-probe] time-before ... peak=2.1359
    [density-probe] step-time ... ratio=0.367879
    [density-probe] frame cost: tick 0.62 -> 6.96 ms (184/23 frames), draw 2.02 -> 6.16 ms (177/18)
    [udpscope]   density: frames=748 rows=4 traces=4 cells=2226150 grid_bytes=8904600 ink=489400.2 peak=2.2 upload_bytes=2226150

`on` `peak=1.0000`, `step-acquisitions` `peak=1.5000` and `step-time` `ratio=0.367879` are the legs
that were expected, unchanged; the *draw* mean is now **below** the run before the split (2.02 -> 6.16
against 2.09 -> 20.91), because the solid traces are no longer drawn over the image.

Docs updated with it: the trigger manual page (`persistence` is the trace, one image per signal, the
newest included), the README's persistence section, `invariants-trigger-and-pinning.md` (five rules,
the ceiling and the no-stroke rule among them), `verification.md` and `probe-readings.md` (the lines
above), the trigger panel's comment and tooltips, and the plotter submodule.

`cmake --build build --clean-first -j4`: **0 errors, the documented three warnings** (two
`MathNode::source`, one `-Woverlength-strings` at 12352); `make -C build test-ui` **13 ok**;
`make -C build test-help` **green** (15 pages); the self-check **0 `Gtk-WARNING`/`Gtk-CRITICAL`** and
`gtk warnings: 0`, two `buffer allocated:` lines.
This commit is contained in:
Martino Ferrari committed 2026-10-16 20:21:57 +02:00
1 parent 5e32199597
commit da826f2cb5
11 files changed
+181 -130

No files matched your search

+6 -4
View File
@@ -115,8 +115,9 @@ precedent, not an exception.
schedule in use, oldest first — halves, and `1/2^age` at that. Both lines and the two exit-dump
lines are in [probe-readings.md](probe-readings.md).
- `UDPSCOPE_PROBE_DENSITY_MS` (+ `UDPSCOPE_PROBE_DENSITY_TAU`, default 1.0 s) — the **phosphor
density**: one screen-sized intensity image every triggered acquisition is accumulated into, drawn
behind the traces, fading by a per-acquisition factor or by a time constant. It states the display
density**: one screen-sized intensity image **per trace**, in that trace's own colour, every
triggered acquisition accumulated into it (the newest included), drawn *in place of* the traces,
fading by a per-acquisition factor or by a time constant. It states the display
**off** through the panel's own switch first, so the `off` leg is the run without it, then arms the
trigger on the mock's `square` with one signal per row — the arrangement the persistence probe uses
— and only then switches it on, so the acquisition already on screen is the first image. Four legs,
@@ -131,8 +132,9 @@ precedent, not an exception.
kill $PY
```
**The assertions, in order:** `off` reads `rows=0 cells=0 ink=0.0 peak=0.0000` (there is no grid at
all); `on` reads `rows=4` — every row has its own image — and **`peak=1.0000`**, one sweep's ink
**The assertions, in order:** `off` reads `rows=0 traces=0 cells=0 ink=0.0 peak=0.0000` (there is no
grid at all); `on` reads `rows=4` — every row has its own image, one per trace in its own colour,
so `traces=4` with one signal a row — and **`peak=1.0000`**, one sweep's ink
being one per cell it covers; `step-acquisitions` reads **`peak=1.5000`**, which is the panel's
0.5 applied to the old image plus the new sweep's own pass; and `step-time` reads
**`ratio=0.367879`**, one step of `dt = tau` through the plot's own `decay_density()`. A `peak` in