Skip to content

fluxa/HorizonTracer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

HorizonTracer

Coming soon. Code and documentation are being prepared for public release. Star/watch this repo to get notified.

A browser-controlled pipeline for producing annotated tracking animations of any solar-system object from plate-solved astrophotography frames. Point it at calibrated XISF data from PixInsight and a JPL Horizons ephemeris file — it handles WCS-based tracking, photometric normalization, optional AI denoising (NoiseXTerminator), zoom animation, and broadcast-quality H.264 encoding with a real-time data overlay.

First built for the Artemis II / Orion MPCV "Integrity" observation campaign at the Southern Carina Observatory (Villarrica, Chile). Works with any target supported by JPL Horizons: spacecraft, comets, asteroids, planets, moons.

The system takes calibrated, plate-solved XISF frames from PixInsight's WBPP pipeline, computes per-frame spacecraft pixel positions via WCS + ephemeris, and renders a tracked MP4 with a real-time data overlay showing RA/Dec, range, phase angle, sky motion, and more.


Features

Core Tracking

  • WCS-based spacecraft tracking — converts JPL Horizons RA/Dec to pixel coordinates using each frame's astrometric solution (PixInsight ImageSolver)
  • Edge clamping — when the spacecraft approaches the source-image boundary, the crop window pins to the edge and the spacecraft drifts naturally out of frame
  • Track smoothing — configurable rolling-average window to suppress single-frame WCS jitter
  • Ephemeris extrapolation — linearly extrapolates past the Horizons file boundary so the track doesn't freeze if the ephemeris is a few minutes short

Frame Processing

  • Photometric normalization — robust median + MAD matching per frame against a reference, removing atmospheric transparency drift and background pedestal changes. Eliminates the "jumpy brightness" problem in time-series animations
  • Auto-locked stretch — normalization automatically pins the display stretch to the reference frame's percentile bounds
  • Temporal smoothing — optional rolling-median over the normalization coefficients to damp single-frame anomalies (satellite trails, meteors)

NoiseXTerminator Integration

  • Headless PixInsight batch denoising — runs NXT on pre-cropped tracking windows via PJSR (PixInsight.exe -n --automation-mode -r=... --force-exit)
  • Tile stitching — groups N crops into composite images with padding to amortize NXT's per-call TensorFlow overhead (~4s/call down to ~0.3s/tile effective)
  • Chunked execution — restarts PixInsight every N composites to avoid CUDA state degradation that causes hangs after ~30 sequential calls
  • Stall watchdog — kills hung PI processes after configurable timeout; the next chunk picks up where it left off
  • Progress tracking — PJSR writes sidecar files that Python polls for live UI progress bars

Zoom Keyframes

  • Dynamic source-window sizing — animate between zoom levels across the timeline (e.g., start wide at 0.5x showing more sky, zoom to 1:1 over 50 frames)
  • Easing functions — linear, ease-in (cubic), ease-out (cubic), ease-in-out (smoothstep)
  • NXT-compatible — precrop tiles are sized to the maximum zoom-out so denoised tiles work at any zoom level without re-processing

Annotation Overlay

  • Data panel — real-time ephemeris display: UTC time, ICRF RA/Dec, range (km + AU), range rate, solar elongation, phase angle, sky motion, frame counter, progress bar
  • Configurable panel placement — 9 anchor positions (corners, edges, center) with pixel offsets, adjustable width and padding
  • Pointer types — crosshair reticle, arrow (fixed angle or auto-along-motion), or none
  • Trajectory line — historical spacecraft path drawn as a polyline in the current crop's coordinate space, with configurable color, width, length (full path or last N frames), and end gap
  • Arrow/trajectory gap — configurable pixel offset so indicators don't obscure the spacecraft
  • Off-screen clamping — when the spacecraft exits the visible crop, the arrow snaps to the nearest frame edge and points toward the actual position
  • Watermark/credit — configurable text, size, and color at the bottom of each frame

Output

  • ffmpeg encoding — pipes raw BGR frames to ffmpeg via stdin for high-quality H.264/HEVC output (replaces OpenCV's soft mp4v codec)
  • Encoder options — libx264 (CRF, highest quality), h264_nvenc (GPU-accelerated), hevc_nvenc (HEVC, smaller files)
  • Output resolution — decoupled from crop size; text and overlays are drawn natively at the higher resolution for crisp rendering
  • Parallel rendering — ProcessPoolExecutor distributes per-frame work across CPU cores; the main thread collects results in order for the sequential video writer
  • Crop-first optimization — stretching runs on the ~360K-pixel tracking window instead of the full 61M-pixel source frame (~170x reduction)

UI

  • Tab-based sidebar — Source, Frame, Image, Annotation, Output (persisted via localStorage)
  • Live preview — single-frame render to PNG for instant parameter tuning
  • Dark astronomical theme — designed for observatory use; low-glare deep-blue palette

Architecture

XISF frames (PixInsight WBPP)
    |
    v
[Scan] ── load WCS + timestamps from each file
    |
    v
[Ephemeris] ── parse JPL Horizons .txt, interpolate/extrapolate to frame midpoints
    |
    v
[Track] ── compute_craft_pixel(WCS, RA/Dec) per frame, smooth, fill gaps
    |
    v
[Normalize] ── (optional) compute (a, b) per frame to match reference median/MAD
    |
    v
[NXT Denoise] ── (optional) precrop -> stitch composites -> PixInsight headless -> unstitch
    |
    v
[Render] ── per frame (parallel):
    |       load XISF (or precropped tile)
    |       apply normalization
    |       crop to tracking window (variable size via zoom keyframes)
    |       stretch to 8-bit display
    |       resize to output resolution
    |       draw annotations (panel, pointer, trajectory, watermark)
    |
    v
[Encode] ── pipe BGR frames to ffmpeg (libx264/NVENC) -> MP4

Modules

File Purpose
artemis_annotator_v2.py Core pipeline: ephemeris parsing, WCS tracking, display stretch, frame annotation renderer
server.py FastAPI web server, global state, all API endpoints, render orchestration
render_worker.py Isolated frame renderer for ProcessPoolExecutor workers (3 render paths: precropped, crop-first, legacy)
normalize_frames.py Photometric normalization via robust statistics (median/MAD) with parallel batch computation
nxt_pipeline.py NoiseXTerminator preprocessing: parallel precrop + headless PixInsight invocation with chunking and stall detection
stitch_pipeline.py Tile stitching/unstitching for NXT composite processing with JSON manifests
video_encoder.py ffmpeg-backed video writer (libx264, h264_nvenc, hevc_nvenc) with cv2.VideoWriter-compatible API
zoom_keyframes.py Keyframe interpolation with easing functions for dynamic zoom animation
tools/pi_nxt_batch.js PixInsight PJSR script for headless batch NoiseXTerminator processing
index.html Single-page browser UI with dark theme, tab navigation, and live preview

Requirements

System

  • Python 3.10+
  • ffmpeg on PATH (for H.264/HEVC encoding; falls back to OpenCV mp4v if missing)
  • PixInsight with NoiseXTerminator (optional, for NXT denoising only)
  • NVIDIA GPU + CUDA (optional, for NXT GPU acceleration and NVENC encoding)

Python Packages

numpy
opencv-python
astropy
Pillow
xisf
fastapi
uvicorn
pydantic

Input Data

  • XISF frames — calibrated, plate-solved mono frames from PixInsight WBPP with astrometric solution in XISF properties (PCL:AstrometricSolution:*)
  • Ephemeris file — JPL Horizons text export with columns 1,2,3,4,5,9,10,18,19,20,23,24,25,47 (see Ephemeris Setup)

Quick Start

# Install dependencies
pip install numpy opencv-python astropy Pillow xisf fastapi uvicorn pydantic

# Start the server
python server.py

# Open in browser
# http://localhost:8642
  1. Source tab — set the frames directory (folder of XISF files) and ephemeris file path, click SCAN FRAMES
  2. Frame tab — adjust crop size (source extraction window) and output resolution (final video pixel size)
  3. Image tab — lock the stretch, run normalization, optionally prepare NXT denoising
  4. Annotation tab — configure the pointer, trajectory, panel placement, and watermark
  5. Output tab — set FPS, encoder, quality, click RENDER MP4

Ephemeris Setup

Generate from JPL Horizons:

Setting Value
Ephemeris Type OBSERVER
Target Body Your target (e.g., Orion MPCV for Artemis II)
Observer Location Your observatory coordinates
Time Span Must cover the full observation window (check frame timestamps)
Step Size 1-2 minutes recommended
Table Quantities 1,2,3,4,5,9,10,18,19,20,23,24,25,47

Important: If the ephemeris doesn't cover the full frame time range, the system will extrapolate linearly from the last two records. A warning is shown during scan. For best accuracy, always extend the ephemeris end time past the last frame by at least 5 minutes.

Required Quantities Mapping

 1  Astrometric RA & DEC           18  Heliocentric ecliptic lon. & lat.
 2  Apparent RA & DEC              19  Heliocentric range & range-rate
 3  Rates; RA & DEC                20  Observer range & range-rate
 4  Apparent AZ & EL               23  Sun-Observer-Target ELONG angle
 5  Rates; AZ & EL                 24  Sun-Target-Observer ~PHASE angle
 9  Visual mag. & Surface Brght    25  Target-Observer-Moon angle / Illum%
10  Illuminated fraction            47  Sky motion: rate & angles

API Reference

Scan & Data

Method Path Description
POST /api/scan Start scanning XISF frames + loading ephemeris
GET /api/scan/status Poll scan progress and results
GET /api/frame-info/{index} Get metadata for a specific frame

Preview & Render

Method Path Description
POST /api/preview Render a single frame as PNG
POST /api/render Start parallel MP4 render
GET /api/render/status Poll render progress
GET /api/download Download the rendered MP4

Display Stretch

Method Path Description
POST /api/lock-stretch Lock stretch to a reference frame's percentiles
POST /api/unlock-stretch Revert to per-frame auto-stretch
GET /api/stretch-status Check lock state

Photometric Normalization

Method Path Description
POST /api/normalize Compute per-frame (a, b) coefficients + auto-lock stretch
POST /api/unnormalize Discard normalization
GET /api/normalize-status Poll normalization progress

NoiseXTerminator

Method Path Description
POST /api/nxt/prepare Start 4-stage NXT pipeline (precrop, stitch, denoise, unstitch)
POST /api/nxt/enable Toggle denoised frame source
POST /api/nxt/clear Forget prepared state
GET /api/nxt/status Poll NXT progress

Zoom Keyframes

Method Path Description
GET /api/zoom-keyframes Get keyframes + interpolated curve
POST /api/zoom-keyframes Set keyframe list
DELETE /api/zoom-keyframes Clear all keyframes

Diagnostics

Method Path Description
GET /api/debug/render-coords Track values, crop bounds, projected reticle position for a frame
GET /api/debug/frame-stats Raw + normalized pixel statistics for a frame

Performance Notes

Benchmarked on i9-13900K (24c/32t), RTX 4090 (24 GB), 64 GB RAM:

Operation Time Notes
Frame scan (164 frames) ~30 s WCS + metadata extraction
Normalization ~10 s 8 parallel workers, 1M-sample stride per frame
NXT prepare (164 frames) ~3-4 min Tile-stitched composites, chunked PI invocations
Render 164 frames (600px) ~15-30 s 8 workers, crop-first optimization
Render 164 frames (1200px) ~30-60 s Larger output, text drawn at native resolution

Project History

Originally developed during the Artemis II mission observation on 2026-04-10 at the Southern Carina Observatory. Built iteratively over one session:

  1. Frame normalization — solved atmospheric transparency flicker using robust median/MAD matching
  2. GPU-accelerated render — crop-first + ProcessPoolExecutor gave ~15x speedup over the original sequential loop
  3. NoiseXTerminator integration — headless PixInsight pipeline with tile stitching to amortize per-call overhead
  4. Zoom keyframes — dynamic source-window animation with easing, composable with NXT denoising
  5. ffmpeg encoding — replaced OpenCV's mp4v codec for dramatically crisper text overlays
  6. Arrow + trajectory overlays — configurable pointer and historical path visualization
  7. Tab-based UI — organized growing control surface into 5 logical groups
  8. Ephemeris extrapolation — fixed frozen indicators when Horizons file was shorter than the observation

License

MIT License. See LICENSE for details.


fluxa | Southern Carina Observatory | Chile

About

Annotated tracking animations of solar-system objects from plate-solved astrophotography + JPL Horizons ephemeris

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors