Asking the fleet what it is doing…
monad-knowledge Wi-Fi sensing lab · FIIT STU
Instrument · from an integer to a probability

A count with a confidence.

A bathroom scale that reads "about 70 kg" is more useful if it can also say "between 68 and 72, nine times in ten", and less useful if the only honest statement is "between 40 and 100". This page asks that of the headcount: for each number of people the instrument can speak for, how likely is that number given one minute's reading, and how wide must a bucket be before the instrument can place a minute inside it with a stated confidence. Every step is computed on this request from the snapshot's own anchors and rows, and every constant is printed with its source.

In plain words A bathroom scale that says 'about 70' is more useful if it can add 'between 68 and 72, nine times in ten'. This page asks that of the headcount: for every number of people the labels can speak for, how likely is it given one minute's reading, and how wide must a bucket be before the instrument can place a minute inside it with a stated confidence.

Anchors and labelled minutes: the occupancy snapshot (web/occupancy_atlas.py, schema 4), method env_inj, 2 labelled anchors over 26 labelled fleet minutes. Minute: 2026-09-07 11:20 library time. Engine: web/counting.py.

Measured days: 2026-08-26 · 2026-08-28 · 2026-08-29 · 2026-08-31 · 2026-09-01 · 2026-09-02 · 2026-09-03 · 2026-09-04 · 2026-09-05 · 2026-09-06 · 2026-09-07 · 2026-09-08 · 2026-09-09 · 2026-09-10. Pass ?date=&tod= for another minute; the level essay shows how this minute's reading was made.

§1

The level law: what each count does to the reading

An anchor is a labelled count and the fleet minutes inside its labelled windows: where their level sat (the median) and how much it wandered (the 10th to 90th percentile). Zero is the certified-empty floor by construction and has no window of its own, so its spread is the p90 of the fleet level over the calibration day's quiet minutes. Between anchors the expected level and its spread are taken as linear in the count; above the top anchor both are flat, because there is no labelled minute above it and the map may not invent one.

L(N) = piecewise-linear through (count, level median)     σ_L(N) = (p90 − p10) / 2·1.2816, floored at 0.03 oct
Fig. 1 · the anchors as knots3 knots
Every knot of the level law. A knot's spread in octaves is one standard deviation; the zero knot's is the empty-floor constant.
PeopleMinutesLevel (oct)σ (oct)Spread from
00.0000.030the quiet minutes' p90 (diary 2026-09-02 §10)
280.8820.265its own p10 to p90
3180.9260.282its own p10 to p90
Edges calibrated on 2026-09-02 (nine receivers, the transmitter-scoped envelope): fleet level 0.00 octaves on 62 quiet minutes (p90 0.03), 1.05 on nine minutes with two moving people, 1.10 on eighteen minutes with three people. Empty against occupied separates; two against three people does not. `high` has never been observed and is a placeholder until the staged crowd days run. Buckets are levels, not head counts.web/counting.py: knots_for, law_at; anchors from web/occupancy_atlas.py: anchors_for.
§2

The resolution ladder: how wide a bucket must be

Two counts are distinguishable when the levels they produce sit further apart than the levels wander. The bucket the instrument can resolve at count N is the level spread there divided by how fast the level moves per person, times the z for the confidence asked. Where the law is flat the slope is zero and the width is unbounded: the instrument has nothing to say. The fitted saturating law is the shape the scattering-budget hypothesis predicts (each mover adds an independent phasor, a finite room caps the effective number), and it needs two labelled counts above zero before it can be fitted at all.

width(N) = 2 · z · σ_L(N) / |dL/dN|     L_sat(N) = ½·log2(1 + A·(1 − e^(−N/K₀)))     z = 1.6449 at 90 %
Fig. 2 · the ladder at 90 %K₀ = 0.95, A = 2.728
Per count: the spread, the slope of the level law in octaves per person, and the bucket width in people that the instrument needs at 90 %. A dash is a slope of zero: unresolved, not resolved.
Peopleσ (oct)Slope, piecewiseWidth, piecewiseSlope, saturatingWidth, saturating
00.0300.4410.22.07270.0
10.1480.4411.10.26041.9
20.2650.04419.70.074211.7
30.282unresolved0.024338.1
4 (above the top label)0.282unresolved0.0083111.4
5 (above the top label)0.282unresolved0.0029321.7
6 (above the top label)0.282unresolved0.0010924.6
Read a row as "at N people, a bucket has to be this many people wide before the instrument places a minute inside it 90 % of the time". The fives family the researcher asked for is honest exactly where the width is five or less. A width that grows past the room's plausible occupancy is the saturation the corpus reports for every variance-type statistic (People Counting by Dense WiFi MIMO Networks: Channel Features and Machine Learning Algorithms (kianoush2019_6c7f) falls from 1.00 to 0.22 accuracy between one and five people on nine receivers). web/counting.py: resolution_ladder, fit_saturating; hypothesis scattering-saturation-link.
§3

One minute's posterior

No labelled anchor above zero, so no posterior. The snapshot's map has nothing to compare a level against.

§4

The check: does it hold on its own labelled minutes?

The posterior is scored on the labelled fleet minutes themselves. This is in-sample, since the anchors were built from these very minutes, so it can refute and cannot confirm: a nested set that misses its own anchors is broken, a set that covers them is not thereby proven. The out-of-sample test is a labelled day the map has not seen, which the crowd-day staircase supplies.

Fig. 4 · coverage on 26 labelled minutesin-sample
Per confidence: how many labelled minutes fell inside their own nested set, and the median set width in people. Coverage at or above the nominal confidence is the minimum a set must reach on the minutes it was built from.
NominalCoveredShareMedian width
50 %19 of 2673 %2
80 %23 of 2688 %2
90 %24 of 2692 %2
95 %24 of 2692 %2
Per bucket family: the mean posterior mass the true bucket received, and the share of minutes on which the true bucket was the most likely one.
FamilyMinutesMass on true bucketTrue bucket is mode
Fives26100 %100 %
Doublings2655 %88 %
The fives family scoring 100 % here is not an achievement: with one label above zero every labelled minute falls in the single open bucket. The doublings row is the informative one. web/counting.py: calibration_check.
§5

What the corpus says, and what would move this page

Every variance-type counting statistic in the corpus saturates. The dense nine-receiver network of People Counting by Dense WiFi MIMO Networks: Channel Features and Machine Learning Algorithms (kianoush2019_6c7f) separates one person from two and then falls to 0.22 accuracy at five. The percentage-of-nonzero-elements metric "almost stopped growing" with the count (A Survey on Wireless Device-free Human Sensing: Application Scenarios, Current Solutions, and Open Issues (xiao2023_6732)). Device-free crowd counting with WiFi channel state information and deep neural networks (zhou2020_6173) reaches 0.11 person mean error at up to 34 people, but only with a trained network, twelve labelled counts, and the finding that a missing count in training degrades the rest. Nothing in the corpus reports a count with an interval over a day of unlabelled minutes; the coverage tables above are this project's own.

Two things move this page. A second labelled count fits the saturating law and fills the right half of the ladder. A labelled day the anchors did not see turns §4 from a refutation-only check into a coverage measurement, and that is where the conformal wrapper of the conformal-count-intervals hypothesis takes over from the normal likelihood used here. Until then, a bucket of five is one open bucket on this instrument, and the page says so.

Related: how this minute's level was made · the episodes with their 90 % sets · the calibration panel · JSON: minute · ladder and check