focus: a reading that cannot rise is not a measurement - #34
Conversation
Found by running the sweep against a real lens. On an 85H50AI the bank being measured moved 2.6x across a defocus sweep on its own sum -- and the sweep reported "falls to 1/1.0", because its peak zone sat on 65535 at both ends. 34 of 255 zones were pinned there. The per-zone accumulators are u16, and a zone at the top of that range has stopped measuring: the filter's real response went higher and the counter could not say so. A pinned value cannot fall, so a sweep across one reports that nothing changed -- indistinguishable from a filter that genuinely cannot see focus, and needing the opposite fix. Cut the gain, or change the filter. They must not produce the same number. summarise() now returns `saturated` and `peakSaturated`. Reported, not subtracted: dropping a pinned zone would hand back some lower zone's value as though it were the peak. Only h2 and v2 count, the two the blend is made of -- h1 and v1 belong to the other bank and never reach the reported value. This is NOT `clipped`, which is about the picture: pixels over the high-luma threshold, a specular highlight in an otherwise fine zone. A saturated zone can be perfectly exposed. What is full is the counter, and the cause is the filter's gain, not the scene. The live grid names the count and whether the sharpest zone is among them. The sweep counts pinned readings at every position and, given any, refuses to state a ratio at all -- it says which knob fixes it instead. A filter that is merely flat still gets its honest 1/1.0; being pinned is the only thing that buys an excuse. Ten checks, every guard mutation-tested: breaking it turns exactly the checks written for it red.
PR Summary by QodoDetect saturated focus zones and reject invalid sweep ratios
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1.
|
Review caught a real hole. Peak selection keeps the first strict maximum,
so a saturated zone can tie with an unsaturated one and lose: {h2: 65534,
v2: 5} and {h2: 65535, v2: 0} both blend to 55295. Reading the flag off the
winning index alone let grid ORDER decide whether the reading was
trustworthy -- the pinned zone was equally the peak, and the sweep went on
to print a ratio over it.
If anything at the top of the grid cannot rise, the peak cannot rise.
|
Real, and the example is exact — fixed in 867fa3f.
peakSaturated: peakAt >= 0 &&
fv.some((v, i) => v === peak && state[i] === 'measured' && sat[i]),If anything at the top of the grid cannot rise, the peak cannot rise. Tested with that exact pair, in both orders, with the tie itself asserted first so the test cannot quietly stop being a tie if the blend constants ever change. Mutation-checked: restoring
|
Found by running v0.16.0's sweep against a real lens on an 85H50AI.
The bank being measured moved 2.6× across a defocus sweep on its own sum — and the sweep reported "falls to 1/1.0". Its peak zone sat on 65,535 at both ends; 34 of 255 zones were pinned there.
The bug
The per-zone accumulators are u16. A zone at the top of that range has stopped measuring: the filter's real response went higher and the counter could not say so. A pinned value cannot fall, so a sweep taken across one reports that nothing changed — which is indistinguishable from a filter that genuinely cannot see focus, and needs the opposite fix. Cut the gain, or change the filter. They must not produce the same number.
The fix
summarise()returns two new fields:saturated— how many zones are at the ceilingpeakSaturated— whether the zone that set the peak is one of them, which is what actually makes a sweep flatReported, not subtracted. Dropping a pinned zone from the peak would hand back some lower zone's value as though it were a measurement; the honest answer is that the peak is real but cannot rise, and the caller is told so.
Only
h2andv2count — the two the blend is made of.h1andv1belong to the other bank and can sit at the ceiling all day without touching the value this page reports.This is not
clipped. That one is about the picture: pixels over the high-luma threshold, a specular highlight in an otherwise fine zone. A saturated zone can be perfectly exposed. What is full is the counter, and the cause is the filter's gain, not the scene.What the operator sees
The live grid names the count, and whether the sharpest zone is among them. The sweep counts pinned readings at every position and, given any, refuses to state a ratio at all — saying which knob fixes it instead of returning a number that looks like a measurement.
A filter that is merely flat still gets its honest
1/1.0. Being pinned is the only thing that buys an excuse, and there is a test for that direction too.Tests
Six assertions in
tools/smoke.mjs, four intests/ui-check.html. Every guard mutation-tested — breaking it turns exactly the checks written for it red:v2at the ceiling ignorednode tools/smoke.mjsandnode tools/ui-check.mjsboth pass.