feat: the manual is a Mallard set opened in Yelp, not a GResource in the binary
The help was 14 Pango-markup `.txt` bodies in a second GResource, drawn into a paged `GtkWindow` built in `help_window.cpp`. That made F1 a viewer of ours with no search index, no cross-references and no translation, and it kept the manual in the *binary* when every other desktop application's is a document on disk. It is now a real Mallard set: help/C/org.udpscope.app/ index.page + 14 topic pages + figures/*.png and `show_help()` hands `help:org.udpscope.app` to whatever the desktop registered for the `help:` scheme -- Yelp on GNOME -- through a `GtkUriLauncher`, reporting a launch failure with a `GtkAlertDialog` rather than a click that silently does nothing. The paged window's builder, the page table and `help_self_check()`'s markup validation are gone with the resource. The document identifier is the desktop file's own basename (its desktop-file id), derived in CMakeLists from `data/org.udpscope.app.desktop.in`, so the same string is the `.desktop` name, the GApplication id and the install directory at once. The set is installed by a new `install()` rule to `<datadir>/help/C/org.udpscope.app/` -- where the freedesktop Help System Specification's `help:` URI resolves `help:<id>` -- so the manual is read from a datadir by another process even though the binary has no install step. `UDPSCOPE_HELP_NAME` and `UDPSCOPE_HELP_DIR` are compiled in from that one place. The 14 pages were migrated fact for fact, but restructured the Mallard way: a `<desc>` per page (what a search result shows), `<steps>` for procedures, `<terms>` for option lists, `<gui>`/`<key>`/`<keyseq>` for interface words and keys, `<note>` for the asides, and a topic graph via `<link type="guide" xref="index#main"/>`. The figures are annotated screenshots produced by `tools/make-help-shots.sh`, which drives the app headlessly against `tools/mock_udpstreamer.py` and draws the boxes with ImageMagick; the side panel's box is measured from the app's own `side=NNNx` dump reading, the header and status bands come from a documented table, and a crop whose standard deviation is 0 fails the script. `cmake --build build --target test-help` checks the set the way `test-ui` checks the `.ui` files: `yelp-check`'s offline subcommands (links, media, orphans, ids) and a `yelp-build html` render. `yelp-check validate` is deliberately absent -- it fetches the Mallard RelaxNG schema over the network and fails offline for that reason, not for a fault in the pages. The `[help]` probe reading changes with the resource it was written for. `parsed == pages` over in-binary markup cannot exist now, so `help_self_check()` scans `UDPSCOPE_HELP_DIR` and the line reads `topics=14 index=1 figures=3`; `topics=0 index=0` is the manual missing from the tree, which is the finding the old count named. Verified: clean build with the documented three warnings (the help bundle's `-Woverlength-strings` is gone, so the baseline moves from four to three); test-ui 14/14; test-help clean (the four subcommands and 15 pages rendered); a temp-prefix install lands 15 `.page` files and 3 figures at `share/help/C/org.udpscope.app/`; the headless run reads `[help] topics=14 index=1 figures=3 dir=...` with 0 Gtk-CRITICAL. Yelp's own window could not be exercised on this box -- it starts under Xvfb, activates its portals and never maps, the same WebKit/portal limitation that stops a grab -- so its rendering and its search index are unverified here; the content pipeline was (`yelp-build` renders the whole set). Docs: the manual's build/install/open story in `build-and-run.md` and README; the warning baseline in `verification.md`/CLAUDE.md; the help bullets in `invariants-gtk-and-chrome.md`; the `[help]` line in `probe-readings.md`.
This commit is contained in:
1 parent
620473a5be
commit
c1460a6977
47 files changed
+1910
-1056
No files matched your search
@@ -0,0 +1,97 @@
|
||||
<page xmlns="http://projectmallard.org/1.0/"
|
||||
type="topic" style="task"
|
||||
id="measurements">
|
||||
|
||||
<info>
|
||||
<link type="guide" xref="index#analysis"/>
|
||||
<link type="seealso" xref="cursors"/>
|
||||
<desc>A measurement is a statistic of the visible window of one signal, with optional
|
||||
on-plot marks and a per-measurement statistics line.</desc>
|
||||
<credit type="author copyright">
|
||||
<name>Martino Ferrari</name>
|
||||
</credit>
|
||||
</info>
|
||||
|
||||
<title>Measurements</title>
|
||||
|
||||
<p>A measurement is a statistic of the <em>visible window</em> of one signal, recomputed as
|
||||
that window moves. The pane lists them with their values; each can also draw its result on
|
||||
the plot.</p>
|
||||
|
||||
<section id="reach">
|
||||
<title>How to reach it</title>
|
||||
<steps>
|
||||
<item>
|
||||
<p>Press the measurements button in the toolbar, or <key>m</key>.</p>
|
||||
</item>
|
||||
<item>
|
||||
<p>The pane's <gui>+</gui> adds one; clicking a row opens the dialog where the signal,
|
||||
the type, the threshold share and the on-plot marks are set, with <gui>Save</gui> and
|
||||
<gui>Delete</gui>.</p>
|
||||
</item>
|
||||
</steps>
|
||||
</section>
|
||||
|
||||
<section id="knowing">
|
||||
<title>Worth knowing</title>
|
||||
<list>
|
||||
<item><p>The types are average, top, bottom, min, max, peak to peak, amplitude, pulse
|
||||
duration, period and frequency. <em>top</em> and <em>bottom</em> are the means of the
|
||||
upper and lower halves, which is why a unit sine reads 0.637 (2/π) rather than 1.</p></item>
|
||||
<item><p>The on-plot marks come in two kinds and the mix is the reading: a <em>level</em>
|
||||
mark is a ruler at a value, a <em>time</em> mark is a marker at a position. An average
|
||||
draws one level mark; a max draws a level mark <em>and</em> a time mark at the first
|
||||
sample that reached it.</p></item>
|
||||
<item><p>Marks cannot be dragged. A measurement mark says what the measurement measured,
|
||||
so it is created unselectable — as is the trigger marker.</p></item>
|
||||
<item><p>A pass is throttled to a cadence rather than run every frame, so a ruler over a
|
||||
live view is <em>stepped</em>. The number and the ruler come from the same pass, so they
|
||||
always agree.</p></item>
|
||||
<item><p>An invalid pass keeps its <em>level</em> marks and drops its <em>time</em>
|
||||
marks. A level is a property of the signal and outlives the window; a position inside
|
||||
the window does not. That is what stops the rulers blinking off at a mode change.</p></item>
|
||||
<item><p>A crossing is counted with <em>hysteresis</em>, not on a bare level: the
|
||||
thresholds are a tenth of the window's peak to peak either side of the share, and an
|
||||
edge is counted only once the signal has passed the far one. Period, frequency and pulse
|
||||
duration all depend on it. The mid level is exactly where a waveform moves fastest, so
|
||||
any interferer faster than the fundamental recrosses a single level several times per
|
||||
real crossing — a 5 Hz sine with a 500 Hz tone at a tenth of the amplitude reads 39 Hz
|
||||
without the band and 5 Hz with it. The band holds to an interferer a third of the
|
||||
waveform's own size.</p></item>
|
||||
<item><p>The band is clamped to stay inside the data, which is what keeps a threshold set
|
||||
near an extreme usable: a fixed band there would sit above every sample and the
|
||||
measurement would read nothing. A share near an extreme still leaves the band little
|
||||
room, so it rejects less — which is one reason period and frequency offer no share to
|
||||
set.</p></item>
|
||||
<item><p>A window with too few crossings reads <code>invalid</code> / <code>--</code>
|
||||
rather than a plausible invented number. Frequency over a window holding one edge is the
|
||||
usual case.</p></item>
|
||||
<item><p><gui>frequency</gui> is reported in Hz and <gui>period</gui>/<gui>pulse
|
||||
duration</gui> in seconds; every other type carries the channel's own unit. A value is
|
||||
written with a <em>metric prefix</em> so its digits sit in <code>1..999</code> —
|
||||
<code>636.62 mV</code>, not <code>0.64 V</code> — including when the stream declares no
|
||||
unit at all, which is always the case for a math channel: there the prefix goes tight
|
||||
against the number (<code>636.62m</code>), since two decimals of an unprefixed small
|
||||
value is <code>0.00</code>.</p></item>
|
||||
<item><p>Cost is bounded by reading the summary pyramid the producer already maintains,
|
||||
not the raw window. The values are still exact: a bucket's sum is a sum.</p></item>
|
||||
<item><p><gui>Statistics</gui> adds a second line to every measurement showing
|
||||
<code>n</code>, the mean, the standard deviation and the range. Each observation is one
|
||||
<em>recompute</em> of the pane, so <code>n</code> counts windows measured, not samples —
|
||||
a mean frequency over many windows is what that claims to be. <gui>Reset</gui> clears
|
||||
every accumulator and starts fresh. A change of display window, a CONFIG or a
|
||||
measurement edit also resets; a pause, a resume, a zoom, a pan and the toggle itself do
|
||||
not, so turning the line off to read the plot and back on again keeps the history.</p></item>
|
||||
</list>
|
||||
</section>
|
||||
|
||||
<section id="example">
|
||||
<title>Example</title>
|
||||
<p>On a 1 Hz ±1 sine: <code>average=0</code>, <code>top=0.636620</code>,
|
||||
<code>bottom=-0.636620</code>, <code>max=1</code>, <code>min=-1</code>,
|
||||
<code>peak to peak=2</code>, <code>amplitude=1</code>, <code>pulse duration=0.5 s</code>
|
||||
(duty 0.5), <code>period=1 s</code>, <code>frequency=1 Hz</code>. Over a 2 M-sample window
|
||||
those two passes read about 0.1% of the samples.</p>
|
||||
</section>
|
||||
|
||||
</page>
|
||||
Reference in new issue
Block a user