Skip to content

feat(photos): star trail per night session in photos sort - #302

Merged
joepetjr merged 1 commit into
mainfrom
feat/photo-sort-star-trails
Nov 10, 2026
Merged

joepetjr merged 1 commit into
mainfrom
feat/photo-sort-star-trails

Conversation

@joepetjr

Copy link
Copy Markdown
Contributor

What

photos sort now builds one star trail per night session, after the stacks and before the time-lapse (follow-up named in #300):

  • Output. trails/<first-group-id>.tif is the 16-bit master and trails/<id>.jpg is the browser JPEG, via night_products.render_master_preview. Each trail appends Output("trails", id, "trails/<id>.jpg"), so the feat(photos): one card per sequence on the sort index page #299 card shows it between the stacks and the video.
  • Engine. It renders through the existing astro_trails.render_trail (calibrated, unaligned, streaming per-pixel maximum), behind the preflight_trail RAM/disk gate. A new GroupOps.star_trails seam wraps it.
  • One triage per session. classify_night runs at most once per session, and both the trail and the time-lapse use its result. Lens-cap darks are never used as lights. Darks calibrate only when build_validated_master_dark accepts them; that check is now the shared _validated_darks helper. A maximum keeps an unsubtracted hot pixel forever, so an unmatched set is dropped.
  • Threshold. TRAILS_MIN_FRAMES = 24 usable lights, about 13 minutes at the measured 32 s interval. A shorter session stores trails-skip:v1, so --resume doesn't decode it again.
  • Resume and failure. These match the time-lapse: the ledger key is group_key("trails", members) + stack:v1. A failure becomes a skipped.csv row, its partial files are removed, and the run goes on. --no-stacks skips trails.

Real-data smoke (default seam, no stubs; 2026-11-09 run, night-1, output to a scratch dir)

  • night-1: 19 RAWs → sg._star_trails → night-1.tif (107 MB) + night-1.jpg (3.1 MB) in 124 s at nice 19, beside a running photos sort --reprocess.
  • I looked at the JPEG: even dashed arcs across the whole sky over the treeline and ridge, as the astro_trails docstring expects for this camera's 15 s exposures on a 32 s interval. It is not black and shows no hot-pixel field.
  • The two real sessions are 76 and 94 frames, so roughly 8 and 10 minutes each at this rate.

Test plan

  • Red: pytest -n 0 -p no:cacheprovider --no-cov -q tests/test_photo_sort_groups.py → 26 failed with TypeError: GroupOps.__init__() got an unexpected keyword argument 'star_trails' (tests/test_photo_sort_groups.py:118). The shared fake passes the new seam, and the 4 new tests failed too (no sg._star_trails, no trails/).
  • Green: tests/test_photo_sort_groups.py → 34 passed.
  • Final verification: test_photo_sort*.py, test_astro_trails.py, test_astro_timelapse.py, test_docs_numbering.py, test_changelog.py → 129 passed. ruff check and ruff format --check clean. ci/secret_scan.py clean.
  • Refactor: resolved. The dark-validation block moved out of _night_timelapse into _validated_darks, which the trail reuses. Its existing unmatched-darks test still passes.

Regression verified; test-first order not independently enforced.

@joepetjr
joepetjr merged commit d344946 into main Nov 10, 2026
10 checks passed
@joepetjr
joepetjr deleted the feat/photo-sort-star-trails branch November 10, 2026 15:59
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