test: the noise probe reads the de-noise node, and the math probe builds one
The probe gains a staged chain rather than one phase, and the schedule moves with it: `UDPSCOPE_PROBE_NOISE_MS` now times the *setup* stage, which installs the de-noise graph through `apply_math_channels()` -- a structural rebuild that replaces the buffer and drops its history -- five seconds before anything scans it. The legs and the five measurements then run at about 10.5 s, and the reading that says the median rejected every impulse at 15.5 s, so the documented run needs a 20 s mock and an 18 s exit. The de-noise channel is installed **disabled** and enabled only at 13 s, for its own reading. An acquired channel is a share of the ring, so a fifth one shortens every channel's retained span -- and the six `BufferSearch` leg counts and `pkpk bare` are all peaks and counts *of that window*. Installing it enabled (as the plan had it) moved `bare` from 49 to 21, `ratio` from 7.00 to 3.00 and `pkpk bare` from 2.988 to 2.488, i.e. it would have rewritten the older feature's documented proof to record a regression that is not one. With it enabled only at the end, every reading from Tasks 4 and 8 is bit-for-bit what the doc records, and the new line reads `denoise raw=2.987696/1 denoised=2.000000/1 ratio=0.669 channels=1` -- `denoised` exactly the clean sine's 2.0, which is the claim the node makes. Two other findings, both folded in: a derived channel whose source is switched off through the panel's checkbox follows it off and does *not* come back when the source returns (the enable-all probe's last act switches `sine` off at ~3 s), and the probes reload leftover math channels from `$XDG_CONFIG_HOME/udpscope`, which is why a `setup channels=` count above 1 means an earlier run's session, not a defect. `math_probe` gains a third channel with a `DeNoise` node so the editor's median row is built and synced on a baseline run: `3 math channels on 'sine' and 'noise'`, every other line as before, `math cost: 103.3 ns/slot` (one reading of the same path). verification.md: the recipe, and why the two stages may not be collapsed -- a probe that rebuilt the buffer under its own legs reads `bare=0` and looks like a broken comparator. Also that the noise and math probes may not share a run: both write `app.math`.
This commit is contained in:
1 parent
5c2c221777
commit
c38630643d
6 files changed
+181
-21
No files matched your search
@@ -1284,19 +1284,41 @@ while the edit runs) and never falls to 0, which is what a rebuild would do. Eve
|
||||
## `[noise-probe]`
|
||||
|
||||
```
|
||||
[noise-probe] setup channels=1
|
||||
[noise-probe] trigger band: bare=49/2 band=7/2 ratio=7.00
|
||||
[noise-probe] trigger hf: hf=7/2 band+hf=7/2 band=7
|
||||
[noise-probe] trigger delay: clean=4 filtered=4 delay=0.002206 want=0.002206 ratio=1.000
|
||||
[noise-probe] trigger hf: hf=7/2 band+hf=6/2 band=7
|
||||
[noise-probe] trigger delay: clean=3 filtered=4 delay=0.002206 want=0.002206 ratio=1.000
|
||||
```
|
||||
|
||||
`UDPSCOPE_PROBE_NOISE_MS`, and it needs the mock's **spiked** sine -- `--spike-every 0.005 --spike-amp 0.5
|
||||
--spike-width 2` -- where every other probe uses the plain mock. It arms in two phases: the first enables the
|
||||
signals it measures *itself*, because a probe must not depend on another probe's side effects
|
||||
(`enable_all_probe` ends by switching one off again, which is how `sine` went missing from the first run of
|
||||
this one), and waits 2.5 s for the ring to refill after that structural change. The legs then each search the
|
||||
whole retained buffer through `BufferSearch`, one after another **without yielding**, so all six see the same
|
||||
buffer.
|
||||
--spike-width 2` -- where every other probe uses the plain mock. It runs as **four stages**, and the chain is the point:
|
||||
|
||||
1. At `UDPSCOPE_PROBE_NOISE_MS` the setup installs the de-noise graph through `apply_math_channels()`.
|
||||
That is a structural rebuild that *drops the buffer's history*, so the five seconds to the next stage are
|
||||
what let the ring refill before anything scans it.
|
||||
2. Five seconds later the legs run. They enable the signals they measure *themselves*, because a probe must
|
||||
not depend on another probe's side effects (`enable_all_probe` ends by switching one off again, which is
|
||||
how `sine` went missing from the first run of this one), and wait 2.5 s for the ring to refill after that
|
||||
structural change. The legs then each search the whole retained buffer through `BufferSearch`, one after
|
||||
another **without yielding**, so all six see the same buffer -- and the five measurements come next, over
|
||||
the same retained history.
|
||||
3. Two and a half seconds later the de-noise channel is **enabled**, by name, through the same switch the
|
||||
panel drives. The setup installs it *disabled* and this stage turns it on, because an acquired channel is
|
||||
a share of the ring: a fifth one shortens *every* channel's retained span, and every figure above scales
|
||||
with that span -- the six leg counts, and `pkpk bare`, which is a peak-to-peak *of the retained window*.
|
||||
The readings above are the older feature's proof, so the new channel stays out of the acquisition plan
|
||||
until they have all run.
|
||||
4. Two and a half seconds after that, the de-noise reading. A math channel starts producing when it is
|
||||
applied *and* acquired, so the channel's first sample is the first one after stage 3, and a peak-to-peak
|
||||
needs a window holding a trough *and* a crest: twelve cycles of the 5 Hz source.
|
||||
|
||||
With `UDPSCOPE_PROBE_NOISE_MS=3000` the legs therefore land at about 10.5 s and the last line at 15.5 s,
|
||||
which is why the documented run needs `UDPSCOPE_EXIT_AFTER_MS=18000`.
|
||||
|
||||
- **`setup channels=1`** -- one math channel was installed, and it is printed by the *first* stage, before
|
||||
any leg: it is the line that says the graph exists at all. A count above 1 means a session file from an
|
||||
earlier run was loaded on top of it (`$XDG_CONFIG_HOME/udpscope`); those channels load disabled, so they
|
||||
do not change the partition, and a clean run of the documented command prints `1`.
|
||||
- **`trigger band:`** -- `bare` is the bare comparator on the spiked sine (every impulse that lands near zero
|
||||
carries it across, so the count is dominated by spikes), `band` the same with a 0.8 band. **`ratio` must be
|
||||
at or above 5**, and `band` about the number of sine cycles retained. Neither count is a *fixed* number:
|
||||
@@ -1324,6 +1346,7 @@ The same probe then puts five measurements on the same spiked `sine` as **two wi
|
||||
[noise-probe] measure period band noise=25.0 hf=0.0 valid=1 value=0.200000
|
||||
[noise-probe] measure period hf noise=0.0 hf=50.0 valid=1 value=0.200000
|
||||
[noise-probe] measure windows=2
|
||||
[noise-probe] denoise raw=2.987696/1 denoised=2.000000/1 ratio=0.669 channels=1
|
||||
```
|
||||
|
||||
- **`pkpk bare`** -- about **3.0**: the sine's 2 plus an impulse either way. The impulses dominate the
|
||||
@@ -1341,6 +1364,18 @@ The same probe then puts five measurements on the same spiked `sine` as **two wi
|
||||
`MeasureOptions::noise_pct`'s own rationale says (10 % holds to a 0.3 interferer).
|
||||
- **`period hf`** -- exactly **0.200000** with the band off: the reject alone. Near `period noband` means the
|
||||
pole coefficient stayed at 1 -- check `measure_filter_set` was given a non-zero `dt`.
|
||||
- **`denoise`** -- the feature under test. `raw` is the spiked sine's peak-to-peak over the visible window and
|
||||
`denoised` the same reading from the **`math denoise`** channel -- a `Source` of `sine` into `DeNoise` with
|
||||
`med_n=5` and `fc=0`, i.e. the median alone. **`denoised` must read exactly `2.000000`**: that is the clean
|
||||
sine's own peak-to-peak, so *not one impulse survived*, which is the whole claim the node makes (the
|
||||
impulses are 2 samples wide and the median is 5, shorter than half a window). `denoised` near `raw` means the
|
||||
median is passing them: check `med_n` arrived as 5 and not 0, since a `med_n <= 0` node returns NaN and a
|
||||
peak-to-peak over holes would read `--` instead. **`denoised=0.000000` with `valid=0` means the channel never
|
||||
produced** -- it was never enabled, its source `sine` was never re-enabled, or `apply_math_channels()` was
|
||||
never called. `ratio` is `denoised / raw` and follows `raw`, which is whatever the visible window's extremes
|
||||
happen to hold: 0.669 here, and up to about 0.8 in a run whose window misses the spike at one extreme. The
|
||||
assertion is on `denoised` and on `raw` being above it; the ratio is the reading, not the test.
|
||||
`channels=` is the math channel *count* (`a->math.size()`), not whether the channel is acquired.
|
||||
- **`measure windows=2`** -- the five legs ask for corners `0, 50, 0, 0, 50` on one channel, which is two
|
||||
distinct windows. **`windows=1` means the corner is not part of the key**: the five collapsed onto one walk
|
||||
and two of them read a signal they did not ask for.
|
||||
Reference in new issue
Block a user