Skip to content

20260915 - Draw the axes over what the node can see, not over what it saw - #89

Merged
Purple10101 merged 2 commits into
mainfrom
20260915-axes-from-the-node
Sep 15, 2026
Merged

Purple10101 merged 2 commits into
mainfrom
20260915-axes-from-the-node

Conversation

@Purple10101

Copy link
Copy Markdown
Collaborator

The Tracker page set no range on either axis, and index() rendered the template with no context at all, so the page never learned what the node was configured to see.

Autoscaling is not a neutral default here. On fairforest B this morning, 97% of the detections were a single interfering tone at 28 Hz, so the Doppler axis collapsed to a sliver around it. The plot looked full and told you nothing about the node's coverage. Two nodes, or the same node an hour apart, get drawn at different scales and cannot be compared. And when the fleet moves to ±300 Hz, the change would be invisible, because the axis was never showing ±200 in the first place.

Where the numbers come from

The node's own blah2 process.ambiguity block, via the merged config retina-gui already reads for the home, config and calibrate pages. Delay arrives in bins and becomes kilometres through capture.fs, since a bin is only a distance once the sample rate says how wide it is.

What happens when they are missing

Anything the config does not state stays None, and that axis autoscales exactly as it does today:

  • no ambiguity block, so both axes autoscale
  • dopplerMin without dopplerMax, so half a span is not half an axis
  • delay bins with no fs, so no delay axis rather than a confident axis over a guessed cell width
  • an unreadable config, so the page still renders

That last one is the point: the axes are a nicety, and losing them must not lose the plot. A guessed range misrepresents the node just as autoscaling does, only more confidently.

uirevision already preserves a viewer's own zoom across updates, so the node's span is where the axis starts rather than somewhere the view is dragged back to.

Also here: how much history is actually held

The window a viewer asks for is what they get only if the node has that much to give. It does not after a restart, and it does not once the sidecar's point ceiling starts ageing the oldest points out, which a wider Doppler span reaches sooner because it raises the detection rate.

The count line now says how much is really held when it falls short of the request, for example 4,312 detections shown · 38m of 4h held. A short record and a quiet sky are otherwise the same picture. This is computed from the data the page already has, by comparing the span it holds against the window it asked for, so it needs no change to the sidecar's stream. A precise dropped-point count would, and is not here.

Verification

ruff check clean, dead-code gate clean, 888 passed.

ruff format --check is not clean, and is not clean on main either: it wants to rewrite single to double quotes across 56 files. This repo's .pre-commit-config.yaml deliberately carries only the dead-code hook, so reformatting is out of scope for this change and would bury it.

Eight new tests in tests/test_tracker_routes.py cover the bounds being read, ±1000 Hz carried through unchanged, delay bins converted through the sample rate, and each of the four ways the bounds can be absent. The last one parses the AXES literal out of the rendered page rather than matching a substring, so it fails if the shape changes rather than only if the numbers do.

Pairs with

retina-tracker #35, which reads the same bounds on the sidecar side and holds arriving detections to them. Neither depends on the other: this one reads the node config directly, so it works against the current sidecar release.

🤖 Generated with Claude Code

Purple10101 and others added 2 commits September 15, 2026 19:19
… saw

The Tracker page set no range on either axis, and the route rendered the
template with no context at all, so the page never learned what the node was
configured to see. Autoscaling is not a neutral default here. On fairforest B
this morning, 97% of detections were a single interfering tone at 28 Hz, and
the Doppler axis collapsed to a sliver around it: the plot looked full and said
nothing. Two nodes, or one node an hour apart, were drawn at different scales
and could not be compared.

The ambiguity bounds are the only honest range. They come from the node's own
blah2 config, which retina-gui already reads for other pages, and the delay
bounds arrive in bins and become kilometres through the sample rate.

Anything the config does not state stays None and that axis autoscales exactly
as it does today. A guessed range misrepresents the node just as autoscaling
does, only more confidently, so half a span is not half an axis and delay bins
without a sample rate are not an axis at all. An unreadable config still
renders the page: the axes are a nicety and losing them must not lose the plot.

uirevision already preserves a viewer's own zoom, so the node's span is where
the axis starts rather than somewhere it is dragged back to.

Also: the window a viewer asks for is what they get only if the node has that
much history to give, which it does not after a restart and does not once the
sidecar's point ceiling ages the oldest points out. A wider Doppler span
reaches that ceiling sooner. The count now says how much is actually held when
it falls short, because a short record and a quiet sky are the same picture.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sweeping the spans found it on the tracker side and the same typo reaches here:
dopplerMin above dopplerMax would draw the axis backwards, and a zero-width pair
would collapse it. Either way a viewer gets a confident picture of nothing,
where autoscaling at least shows the data.

Both halves must be present and the high one above the low one. Everything else
falls back to autoscale, which is the honest answer when the node has not
described itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Purple10101
Purple10101 merged commit c8d629c into main Sep 15, 2026
3 checks passed
@Purple10101
Purple10101 deleted the 20260915-axes-from-the-node branch September 15, 2026 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant