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.
421 lines
18 KiB
XML
421 lines
18 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- SPDX-License-Identifier: MIT -->
|
|
<!-- SPDX-FileCopyrightText: 2026 Martino Ferrari -->
|
|
<!--
|
|
The trigger panel's frame: one labelled row per setting, the pair of buttons that run it
|
|
(Arm/Disarm and Force), and the search block. Its *heading* is not here: the heading row carries the
|
|
switch that turns trigger mode on and off, and this panel's body is what goes insensitive when it is
|
|
off, so the heading has to be its sibling rather than a child of it (`build_trigger_panel()` returns
|
|
the two together).
|
|
|
|
Every row here is a label and a place for a control, and the control itself is built in code. A
|
|
dropdown's model and a spin button's range are the *application's* (the condition list, the level
|
|
range that follows the channel's scale), while a label is text a translator owns, so the split runs
|
|
between them: the row is the file's and the control is appended into it. That is the arrangement
|
|
`labeled_box()` used to make in code, with the label moved where all the other labels are.
|
|
|
|
Between the controls, the labels and the search block are what "read the panel" means, so they are
|
|
here: which of these rows `sync_trigger_rows()` shows depends on the condition (a pulse width has a
|
|
width, a window has two levels, a dropout has a timeout), and that is the code's decision, not this
|
|
file's — this file just has to have a row for each of them to show or hide.
|
|
-->
|
|
<interface>
|
|
<object class="GtkBox" id="trigger_panel">
|
|
<property name="orientation">vertical</property>
|
|
<property name="spacing">6</property>
|
|
<property name="margin-top">8</property>
|
|
<property name="margin-bottom">8</property>
|
|
<property name="margin-start">8</property>
|
|
<property name="margin-end">8</property>
|
|
<child>
|
|
<object class="GtkBox" id="signal_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">signal</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="condition_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">condition</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="edge_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">edge</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="cmp_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">width is</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="width_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">width s</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="width2_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">and s</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="level2_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">to level</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="timeout_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">timeout s</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="level_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">level</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="pre_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">pre-trigger %</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="holdoff_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">hold-off s</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="band_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">noise band</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="hf_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">HF reject Hz</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="mode_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">mode</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="record_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel" id="record_label">
|
|
<property name="label" translatable="yes">record events</property>
|
|
<property name="halign">start</property>
|
|
<property name="hexpand">1</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<!-- The trigger's *display* settings: what the mode does with the acquisitions it takes, as
|
|
against the condition that decides when it takes them. Collapsed by default; a trigger
|
|
is set up once and run for hours, and these are what you come back to when the display
|
|
is what you are looking at. The rows are the file's, as everywhere in this panel; the
|
|
controls are appended into them by `build_trigger_panel()`.
|
|
|
|
Both displays live here and they are two different things: *multiple events* keeps the
|
|
last N acquisitions as N traces, dimmer with age, while *persistence* accumulates every
|
|
acquisition into an image (one screen-sized grid per trace, in that trace's own colour,
|
|
the plotter's `Plot::set_density()`), drawn in place of the traces. The first is a
|
|
count and the second is a decay, which is why neither is a mode of the other. -->
|
|
<object class="GtkExpander" id="advanced_exp">
|
|
<property name="tooltip-text" translatable="yes">what the trigger mode does with the acquisitions it takes: the last few kept as dimmer traces, and a persistence image (one per signal, in its own colour) every acquisition is accumulated into</property>
|
|
<child type="label">
|
|
<!-- A box rather than a plain label, for the search block's reason: the contextual
|
|
help's "(i)" joins its last child and a hint hung on the expander's own *child* is
|
|
off screen while the block is collapsed (see
|
|
docs/claude/invariants-gtk-and-chrome.md). -->
|
|
<object class="GtkBox" id="advanced_head">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">Advanced</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<property name="child">
|
|
<object class="GtkBox" id="advanced_box">
|
|
<property name="orientation">vertical</property>
|
|
<property name="spacing">6</property>
|
|
<property name="margin-top">4</property>
|
|
<child>
|
|
<object class="GtkBox" id="persistence_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel" id="multiple_event_label">
|
|
<property name="label" translatable="yes">multiple events</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="density_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel" id="density_label">
|
|
<property name="label" translatable="yes">persistence</property>
|
|
<property name="halign">start</property>
|
|
<property name="hexpand">1</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="density_decay_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">fades by</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="density_tau_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">time constant s</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="density_factor_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">per acquisition</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</property>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox" id="arm_row">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkButton" id="trigger_arm">
|
|
<property name="label" translatable="yes">Arm</property>
|
|
<property name="hexpand">1</property>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkButton" id="trigger_force">
|
|
<property name="label" translatable="yes">Force</property>
|
|
<property name="hexpand">1</property>
|
|
<property name="tooltip-text" translatable="yes">take one acquisition now, with the pre/post window above, without waiting for the condition</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkExpander" id="search_exp">
|
|
<property name="tooltip-text" translatable="yes">find every place in the retained buffer where the condition above holds, and step through them</property>
|
|
<!-- The header is a box, not a plain label, so the contextual help's "(i)" has a row to join
|
|
as its last child and sits beside the text while the block is collapsed. The block's own
|
|
*child* is not in the widget-parent chain until the expander is expanded (see
|
|
docs/claude/invariants-gtk-and-chrome.md), so a hint hung there would be off screen. -->
|
|
<child type="label">
|
|
<object class="GtkBox" id="search_head">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkLabel">
|
|
<property name="label" translatable="yes">Search the buffer</property>
|
|
<property name="halign">start</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<property name="child">
|
|
|
|
<object class="GtkBox" id="search_sbox">
|
|
<property name="orientation">vertical</property>
|
|
<property name="spacing">4</property>
|
|
<property name="margin-top">4</property>
|
|
<child>
|
|
<object class="GtkBox">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkButton" id="search_run">
|
|
<property name="label" translatable="yes">Search</property>
|
|
<property name="hexpand">1</property>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkButton" id="search_cancel">
|
|
<property name="label" translatable="yes">Stop</property>
|
|
<property name="sensitive">0</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkLabel" id="search_status">
|
|
<property name="label" translatable="yes">not searched</property>
|
|
<property name="halign">start</property>
|
|
<property name="wrap">1</property>
|
|
<property name="css-classes">dim-label</property>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkBox">
|
|
<property name="orientation">horizontal</property>
|
|
<property name="spacing">6</property>
|
|
<child>
|
|
<object class="GtkButton" id="search_prev">
|
|
<property name="icon-name">go-previous-symbolic</property>
|
|
<property name="tooltip-text" translatable="yes">the previous hit</property>
|
|
<property name="sensitive">0</property>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkLabel" id="search_pos">
|
|
<property name="label">--</property>
|
|
<property name="hexpand">1</property>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkButton" id="search_next">
|
|
<property name="icon-name">go-next-symbolic</property>
|
|
<property name="tooltip-text" translatable="yes">the next hit</property>
|
|
<property name="sensitive">0</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</child>
|
|
<child>
|
|
<object class="GtkLabel" id="search_marks">
|
|
<property name="label"> </property>
|
|
<property name="halign">start</property>
|
|
<property name="css-classes">dim-label</property>
|
|
<property name="ellipsize">3</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</property>
|
|
</object>
|
|
</child>
|
|
</object>
|
|
</interface>
|