Asking the fleet what it is doing…
monad-knowledge Wi-Fi sensing lab · FIIT STU
Instrument · one minute, from the beginning

How a level is made.

Think of a room with a ticking metronome and nine microphones. In an empty room every tick comes back the same; people walking through make the echo flutter. The occupancy app turns that flutter into one number per minute. This page follows one real minute from the flutter of a single frame to the headcount, one declared step at a time: a scalar per frame, a quarter-second window, a minute, a floor, an octave, a bucket, a fleet, a count. Every step is the reduction's own code or the snapshot's own row.

In plain words Think of a room with a ticking metronome and nine microphones. An empty room returns the same tick every time; people walking through make the echo flutter. This page takes one real minute and shows each step from the flutter of one frame to a headcount with an honest interval around it.

Frames and windows: the committed sample envelope-csiq (monad04_walk-raster-48_20260825-120604, 397 frames in 0.18 s), reduced on this request by lake/ingest.py's own functions. Minute onward: the occupancy snapshot (web/occupancy_atlas.py, schema 4), the row the app shows for 2026-09-02 11:20 library time.

Capture for the frame stages: band-2.4__condition-clean__width-HT20 · band-5__condition-clean__width-HT20 · band-5__condition-quarantined__width-HT20 · band-5__condition-clean__width-HT40+ · band-5__condition-clean__width-80MHz · envelope-csiq · envelope-csiq.zst · writer-modern · writer-legacy · band-6 · Minute: open the day in the app

§1

A frame becomes a number

The reduction never keeps a record's table. From each frame it keeps two scalars: the median over tones of the two-chain ratio's size in decibels, and the circular median of its angle. The first is the envelope observable; the second feeds the motion statistic. Both survive the card's per-frame gain, because both chains share it.

ratio_amp_db = median_k 20·log10 |H₀(k)/H₁(k)|     one per frame, stored in packets
Fig. 1 · the per-frame scalar397 frames
The first forty frames' scalars.
t (s)ratio_amp_dbratio phase (rad)
0.000-0.1980.2543
0.0000.1770.5954
0.000-0.1230.2594
0.000-0.20.3158
0.001-0.1740.2685
0.0010.1890.5731
0.0010.1920.6018
0.0030.2520.5582
0.0030.1520.5983
0.003-0.2220.2852
0.0030.2390.6183
0.003-0.1150.3004
0.004-0.2480.2126
0.0040.1570.5259
0.0050.2050.6042
0.0060.2830.568
0.0060.2060.5112
0.0060.2610.6275
0.007-0.1170.2763
0.007-0.0990.2517
0.0070.2070.626
0.0070.1540.5634
0.007-0.1110.1897
0.007-0.1650.2852
0.0080.1880.5518
0.008-0.2180.285
0.008-0.0880.2676
0.0090.2040.5167
0.0110.2270.5969
0.0110.1410.6094
0.0110.2060.5433
0.012-0.090.2821
0.012-0.2090.2709
0.0120.1450.6172
0.012-0.1660.2275
0.0120.2460.5202
0.0130.1970.5549
0.0130.2260.5734
0.0140.2110.6013
0.0150.1940.6445
One dot per frame at 2247 Hz; the vertical grid is the quarter-second windows the next step scores. A committed sample is a few seconds of a capture, so the figure shows 1 windows where a minute holds 240.lake/ingest.py:_ratio and the scalar path of decode_segment.
§2

A quarter of a second becomes two statistics

Frames are grouped into 0.25 s sub-windows from the segment's first frame. A window with fewer than thirty frames is not scored, which is the 120 Hz floor under every statistic on the site. In a scored window, the standard deviation of the frame scalars is the envelope statistic, and the unnormalised Lomb–Scargle power of the unwrapped, detrended ratio phase in the 20 to 60 Hz band, divided by the frame count, is the walker statistic.

envelope = sd(ratio_amp_db) over the window     doppler_20_60 = ∫ P_LS(f) df / n, f ∈ [20, 60] Hz
Fig. 2 · the sub-windows1 of 1 scored
Every sub-window of the sample: frames, the envelope statistic and the two Doppler band powers. A window under thirty frames is not scored.
WindowFramessd (dB)Doppler 20–60Doppler 5–20Scored
03970.19060.0031390.001699yes
Bars are the envelope statistic per window, dots the walker band power. The minute's row in the lake is the standard deviation of the frame scalars over the whole minute and the mean of the scored windows' band powers; the per-window values are what the 2-second motion table keeps.lake/ingest.py:_band_power, SUBWINDOW_SECONDS; measurement-lake skill, "Occupancy and motion are two questions".
§3

A minute becomes an octave

Each receiver's minute is the standard deviation of its frame scalars over the injector's frames. It is divided by that receiver's own floor: the median of its certified-empty night minutes when the day has thirty of them (rule A), else the day's own tenth percentile (rule B), and the rule is stored beside the number. The quotient in base-two logarithm is the level in octaves: one octave means the spread doubled against the empty room.

level = log2( value / floor )     buckets at 0.25, 0.75, 1.5 octaves
Fig. 3 · every receiver's octave, 2026-09-02 11:209 receivers
Per receiver: the minute's raw statistic, its floor and rule, the level and the bucket.
Receivervalue (dB)floor (dB)rulefloor minuteslevel (oct)bucketrate (Hz)
monad020.05890.0425A880.47low207
monad030.07740.0361A881.10occupied209
monad040.05890.0348A880.76occupied222
monad050.05590.0407A880.46low42
monad060.05150.0268A880.94occupied213
monad070.07020.0631A880.15empty52
monad080.12070.0573A881.07occupied170
monad090.11940.0337A881.82high133
monad100.10960.0712A880.62low66
The floors differ threefold between receivers and moved within a morning, while people multiplied them by about two everywhere; that is why the level is a ratio in octaves and not a difference in decibels. A person labelled this minute: OL-003, 3 people.web/occupancy_atlas.py: floors_for, level_of, EDGES; diary 2026-09-02 §4b.
§4

A fleet becomes a probability, and a probability a count

The fleet level is the median over the receivers that scored the minute, at least 3 of them. The receivers are resampled 1000 times and the median recomputed; the 5th and 95th percentiles of those medians are the band, and the share of them that fall in each bucket is the bucket's probability. Nine receivers on one illuminator is an optimistic n, and the band is labelled a receiver bootstrap wherever it appears.

P(bucket) = share of bootstrap medians in the bucket     count = map⁻¹(level) through the anchors
Fig. 4 · the bucket probabilitiesfleet 0.76 oct
The fleet row for this minute, and the count the map returns.
ReceiversFleet level5 %95 %P(empty)P(low)P(occupied)P(high)Most likelyPeople
90.7590.4711.0740.1 %40.1 %59.6 %0.2 %occupied (60 %)2 (1 to 3 or more)

Anchors of the count map: 0 → 0.00 oct; 2 → 0.88 oct (p10 0.50, p90 1.18, 8 min); 3 → 0.93 oct (p10 0.48, p90 1.21, 18 min).

The count is the fleet level read through a piecewise-linear map through the anchors, the labelled counts and the level their minutes sat at; zero is the floor by construction and never a label. The interval is the bootstrap band through the same inverse, widened to every anchor whose own spread it touches, which is why two and three people share one interval today.web/occupancy_atlas.py: fleet_for, anchors_for, count_map, counts_for (IP-148).
§5

A count becomes a confidence

The map in §4 returns one integer and one interval at no stated confidence. The same fleet level can instead be read against every count the anchors can speak for: the level each count would produce, its spread, and the minute's own bootstrap band. The result is a probability per count, from which any bucket's confidence follows. Above the top labelled count the instrument cannot tell "3" from "more", so that mass is shown as its own state and never hidden.

P(N | level) ∝ exp( −(level − L(N))² / 2(σ_L(N)² + σ_band²) ) / √(σ_L(N)² + σ_band²)     N = 0 … 3, then "more"
Fig. 5 · the posterior over the countmode 2
Probability per count for this minute, and the smallest run of counts that reaches each confidence.
01234 or more
0.0 %17.3 %29.3 %26.7 %26.7 %

50 %: 2 to 3 (mass 56 %) · 80 %: 2 or more (mass 83 %) · 90 %: 1 or more (mass 100 %) · 95 %: 1 or more (mass 100 %)

Fives. Equal buckets of five people. The graduation the researcher asked for; under a saturating statistic every bucket after the knee costs more confidence than the one before it.
0 or more
100.0 %
Doublings. Zero, one, two to three, four to seven, eight to fifteen. Each bucket is one octave of the count; a statistic that grows with the logarithm of the count spends the same confidence on every bucket.
012 to 34 or more
0.0 %17.3 %56.0 %26.7 %
The prior is uniform over 0 to 3 people and 'more than 3'. The zero anchor's spread is 0.03 octaves, the p90 of the fleet level over the calibration day's quiet minutes; a labelled anchor's spread is its own p10 to p90. A bucket that ends above the top labelled count is open and carries the "more" mass, which is why the fives family reads one open bucket today. The confidence essay shows the law, the resolution ladder and the check behind this table.web/counting.py: posterior_for, nested_sets, family_probs; anchors from web/occupancy_atlas.py.

Related: the app on this day · the episodes · the confidence behind the count · one record of this capture · JSON: frames · minute