Files
udpscope/help/C/org.udpscope.app/measurements.page
T
Martino Ferrari e83ad86b8f measure: top/bottom/amplitude read the flat levels, not the extremes
A bench scope separates Vtop/Vbase from Vmax/Vmin because a band-limited
edge overshoots and rings: the mock's `square` at 30 harmonics reaches
±1.179 where its plateau is ±1. On the rippled square the old readings were
a property of the edges rather than of the waveform -- `top` 0.986496,
`amplitude` 1.179350 -- and `amplitude` reported the overshoot.

`top`, `bottom` and `amplitude` are now the flat levels and their delta.
A flat level is a density question -- the plateau holds most of the
samples and the ringing a few percent -- so `measure_scan_buckets()` folds
a 64-bin histogram of the whole buckets' midpoints while it has the list in
hand (one observation per bucket, each bin carrying its buckets' exact sum
and finite count), and `measure_flat_levels()` takes, either side of the
split, the densest bin holding at least half the densest one's buckets --
the outermost of those, which is what makes a waveform with no plateau read
its peak -- and the exact mean of the samples of the buckets within 5 % of
the window's peak-to-peak of it. 5 % is deliberately under the ~9 %-of-swing
Gibbs overshoot. `amplitude` is `top - bottom` (a scope's Vamplitude), not
the half-swing it was.

Measured, fast mock, 2 s window, harmonics 0 -> 30: top 1.000000 ->
0.999983, bottom -1.000000 -> -0.999983, amplitude 2.000000 -> 1.999966,
while `peak to peak` keeps the extremes (2.000000 -> 2.358701). On the 1 Hz
sine top is 0.957988 (it was 0.636620, the half-wave mean; a sine has no
plateau, so the densest band is at its peak) with sd 0.0014 over a scrolling
window, and `peak to peak` is still exactly 2.

No raw pass and no new fetch: the histogram is the same fetched bucket list
read a second time, gated on a pane that holds one of the three types.
`raw` is unchanged (0.1% clean, 2.1% with the --noise 0.1 interferer,
against 0.1%/2.1% before) for 0.44 -> 0.50 ms and 0.52 -> 0.65 ms a pass.
A window the pyramid cannot summarize -- an hf-filtered walk, or one shorter
than a bucket -- keeps the old readings: the mean of each side of the split,
and the window's peak to peak for amplitude.

Docs: the flat-level invariant (and the two 2/pi assertions it replaces),
the probe readings, the manual's measurements page and the README.
2026-10-15 01:19:33 +02:00

123 lines
7.8 KiB
Plaintext

<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. <gui>top</gui> and <gui>bottom</gui> are the waveform's
<em>flat</em> high and low levels: the level the signal dwells at, taken from the densest
band of the window on each side of the split. A band-limited edge overshoots and rings —
a nominal 2 V square reaches about ±1.18 at its edges — and a ripple or an overshoot is
therefore <em>not</em> what these read. <gui>amplitude</gui> is the delta between those two
levels, and <gui>peak to peak</gui> is the swing between the extremes (so on a rippled
square <gui>amplitude</gui> reads 2 V where <gui>peak to peak</gui> reads 2.36 V).</p></item>
<item><p><gui>top</gui> and <gui>bottom</gui> also read <em>near the peak</em> on a
waveform that has no flat part, which is the honest reading rather than a failure: a unit
sine has no plateau, so the densest band is at its peak and these read about ±0.96 — not
the 0.64 a mean over each half would give, and not ±1 either. Only a level the signal
actually dwells at is a level.</p></item>
<item><p>The <em>split</em> says which side a level is read from, so any share between the
two levels reads the same number; it is not a boundary the value depends on. The one case
where it is read directly is a window the scope cannot summarize by level — a window
shorter than a level's own resolution, or one read through <gui>hf</gui> — where
<gui>top</gui>/<gui>bottom</gui> fall back to the mean of each side of the split and
<gui>amplitude</gui> to the window's peak to peak.</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; <gui>peak to peak</gui> draws a ruler at each extreme and
<gui>amplitude</gui> a ruler at each of its two flat levels — the pair is the span, so
the two rulers <em>are</em> the measurement.</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: a bucket's sum is a sum, so the mean, the extremes and a level's own
mean are exact. <gui>top</gui>, <gui>bottom</gui> and <gui>amplitude</gui> read the
<em>density</em> of the window out of that same summary — which is what tells a flat level
from a ripple — so those three cost a second read of the summary and never of a sample.</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.957988</code>,
<code>bottom=-0.957988</code> (the flat levels, near the peaks — a sine has no plateau),
<code>max=1</code>, <code>min=-1</code>,
<code>peak to peak=2</code>, <code>amplitude=1.915983</code>, <code>pulse duration=0.5 s</code>
(duty 0.5), <code>period=1 s</code>, <code>frequency=1 Hz</code>. On the same stream's
band-limited <code>square</code>, whose edges ring out to ±1.179: <code>top=0.999983</code>,
<code>bottom=-0.999983</code>, <code>amplitude=1.999966</code> against
<code>peak to peak=2.358701</code> — the levels are the plateau's and the extremes are the
edges'. Over a 2 M-sample window those passes read about 0.1% of the samples.</p>
</section>
</page>