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 band-6 (monad04_chan-6ghz-psc5_20260903-175758, 357 frames in 7.88 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-01 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 scalar357 frames
The first forty frames' scalars.
t (s)ratio_amp_dbratio phase (rad)
0.0000.084-0.5477
0.1020.0130.2679
0.1020.06-0.4959
0.2050.0270.3527
0.2050.117-0.5237
0.2130.12-0.5217
0.214-0.0860.5132
0.229-0.1050.4489
0.2290.1150.3144
0.2300.1340.3299
0.230-0.1590.5324
0.2850.048-0.481
0.285-0.1310.4458
0.3000.1210.2867
0.300-0.1260.4805
0.3000.147-0.4896
0.307-0.0090.2671
0.3070.151-0.4885
0.4090.0120.3447
0.4100.094-0.6047
0.5120.076-0.5671
0.512-0.1220.4404
0.5120.056-0.5324
0.5130.085-0.5699
0.6140.13-0.4762
0.6150.020.3221
0.7170.0230.3712
0.7170.166-0.497
0.717-0.0040.2815
0.8190.12-0.5701
0.8190.0190.2844
0.8390.082-0.5566
0.839-0.1560.4717
0.845-0.1530.5014
0.8450.094-0.5595
0.845-0.1150.5522
0.8450.094-0.5416
0.8460.135-0.4584
0.846-0.1610.4925
0.9210.169-0.5602
One dot per frame at 45 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 32 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 32 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
0110.1026no
190.1078no
290.0836no
3160.1206no
460.0846no
5120.1141no
670.0583no
7120.1339no
8140.0987no
960.0376no
1040.0217no
1160.0472no
1240.064no
13100.1281no
1490.1419no
15190.1262no
1680.0761no
1740.0856no
1860.0628no
1990.1306no
20300.09990.0483720.011787yes
2140.0415no
22220.1221no
2340.1202no
24210.1231no
25130.0751no
26170.1112no
27240.1151no
2850.0353no
29150.1059no
3090.0995no
31120.114no
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-01 11:205 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.04540.0231B3370.97occupied230
monad030.05110.0333B3360.62low230
monad070.06740.0611B3360.14empty226
monad090.05560.0352B3370.66low220
monad100.05110.0569B337-0.15empty220
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. No labelled window covers this minute.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.62 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
50.618-0.1550.97232.0 %62.2 %5.8 %0.0 %low (62 %)1 (0 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 1
Probability per count for this minute, and the smallest run of counts that reaches each confidence.
01234 or more
6.9 %28.4 %22.7 %21.0 %21.0 %

50 %: 1 to 2 (mass 51 %) · 80 %: 1 or more (mass 93 %) · 90 %: 1 or more (mass 93 %) · 95 %: 0 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
6.9 %28.4 %43.7 %21.0 %
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