Skip to content

Focus-quality (HFD) indicator on the Focus screen#449

Merged
brickbots merged 5 commits into
mainfrom
worktree-focus-quality-indicator
Jun 3, 2026
Merged

Focus-quality (HFD) indicator on the Focus screen#449
brickbots merged 5 commits into
mainfrom
worktree-focus-quality-indicator

Conversation

@brickbots
Copy link
Copy Markdown
Owner

What

Adds a quantitative, graphical focus aid to the Focus screen (UIPreview). It tells the user how well-focused they are and makes the point of best focus obvious as they sweep through it — independent of plate solving, across the full defocus range.

How

  • PiFinder/focus.py — pure, UI-free module: a self-contained Half-Flux Diameter (HFD) detector (detect_stars, half_flux_diameter, focus_hfd). Runs in the main process on the raw frame; tuned to accept broad/defocused blobs and reject hot pixels / oversized blobs. No dependency on the solver's centroids or SQM (see ADR 0005).
  • UIPreview — a focus strip: fixed log-axis V-curve over a 10 s window, best-focus marker, past-best "BACK UP" cue, HFD/exposure/detected-count/matched-count HUD. Replaces per-frame autocontrast with a background-anchored, EMA-smoothed display stretch. SQUARE toggles the strip; it persists across zoom (HFD is zoom-independent).
  • Testspython/tests/test_focus.py (11 unit tests: Gaussian HFD vs theory, saturated core, blank frame, oversized→too-defocused, monotonicity, median robustness, hot-pixel rejection).
  • Docs — Quick Start "Setting Focus & First Solve" reframed around the HFD readout + V-curve, with HUD example screenshots.

Design references already on main: docs/adr/0005-focus-hfd-self-contained-in-ui.md and the "Focus indicator" section of docs/ax/ui/CONTEXT.md.

Verification

  • ruff / ruff format / mypy clean; pytest -m unit (190, incl. 11 new) and -m smoke (5) pass.
  • Verified live in the headless app: strip renders with live HFD/detected/matched/exposure, empty frames show /det 0, SQUARE toggles the strip, zoom persists it with the relocated Zoom xN label, no crashes.

Notes

  • New UI strings are _()-wrapped and fall back to English until the next nox -s babel; the Babel catalog regeneration is intentionally not included (it swept up unrelated catalog drift).

🤖 Generated with Claude Code

brickbots and others added 5 commits May 29, 2026 11:34
Self-contained Half-Flux Diameter detector (PiFinder/focus.py) plus a focus
strip in UIPreview: log-axis V-curve over a 10s window, best-focus marker,
past-best "BACK UP" cue, and a background-anchored display stretch replacing
per-frame autocontrast. The detector runs in the main process on the raw frame
and does not depend on plate solving, so it works across the full defocus range.

See docs/adr/0005-focus-hfd-self-contained-in-ui.md and the "Focus indicator"
section of docs/ax/ui/CONTEXT.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reframe "Setting Focus & First Solve" around the HFD readout and its V-curve
rather than zooming in to judge stars by eye. Add a focus-strip walkthrough and
HUD example images (focused vs unfocused, with the strip composited over the
existing example frames).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…drop back-up cue

- HFD readout is now a large, right-justified number filling the strip height
  (the hero element); the V-curve and small labels move to the freed left
  region. The no-reading states fall back to a small dim hint ("—" / "keep
  going") instead of a giant placeholder glyph.
- V-curve axis is 4 → 20 px (was 1 → 50): ~4 px is about the best a real
  camera/lens hits and ~20 px is clearly soft, so the trend spends its range
  where it's useful. Out-of-range readings clamp; the numeric readout is exact.
- Display stretch is calmer: lower EMA alpha + larger minimum span cut the
  frame-to-frame brightness swings, and a little uniform dither breaks the
  8-bit banding a narrow stretch otherwise posterised into.
- Remove the past-best "BACK UP" cue and its supporting machinery.
- Update the Quick Start prose and the UI CONTEXT glossary to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The HFD readout and V-curve now carry the focus workflow, so the central
concentric-circle reticle no longer adds anything on the Focus screen.

- Drop draw_reticle() and its zoom-0 call site, plus the unused reticle_mode
  attribute and the orphaned camera_reticle config option (no settings UI).
- Fix a stale comment: the display stretch is numpy + dither, not a LUT.
- Note in the Positioning doc that solve_pixel(screen_space=True) now has no
  UI consumer (the reticle was its only one); the accessor stays.

The Chart/Align Telrad reticle (chart_reticle) is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves conflicts from main's #429 solver/integrator dataclass refactor:
- preview.py: keep the reticle removal + focus-strip work; port
  _matched_star_text() to the new PointingEstimate API
  (solution.solve_source / .estimate_time / .diagnostics.Matches),
  mirroring main's own refactor of that logic.
- docs/ax/positioning.md: take main's solve_pixel -> target_pixel rename,
  keep the note that the Focus-screen reticle (its only consumer) is gone.
- docs/source/quick_start.rst: keep the focus-strip documentation, adopt
  main's leaner opening/closing prose and its +/- zoom tip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@brickbots brickbots merged commit fe07eb0 into main Jun 3, 2026
1 check passed
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