Cosmic Clarity — Satellite Removal

Per-sub satellite trail cleanup, designed for the capture folder. Point the dialog at an input folder of individual subs and an output folder for the cleaned versions, pick a mode, and the AI segmenter finds satellite trails, aircraft streaks, and meteor tracks on each frame and removes them before stacking. Three run modes cover every usage pattern: Single Image for interactive one-off cleanup (operates on the active view or any file on disk), Batch for processing an entire folder of subs in one pass, and Live Monitor for watching the capture folder during an active session and cleaning each file as it lands. XISF, FITS, TIFF, PNG, JPEG, and all major raw camera formats are supported; XISF metadata round-trips so your stacker still gets its CFA and dark-reference info.
SetiAstro Cosmic Clarity Satellite model — original neural network segmenter trained in-house by Franklin Marek on real deep-sky integration data. The model learns to distinguish linear satellite / aircraft / meteor trails from the circular, point-like signature of stars and the diffuse structure of nebulosity, outputting a soft confidence mask that drives either an AI-interpolated inpaint of the affected pixels or a straight clip-to-zero depending on your preference. Model file: satelliteRemovalAI4.pth, shipped with SASpro; nothing talks to a remote server.

1. The three run modes

The three buttons on the left control panel pick how the segmenter is applied:

Why per-sub, not post-stack? Satellite trails hit individual sub-exposures hard but only cover one or two frames out of a hundred. A good stacker's sigma rejection catches most of them. The segmenter here handles the rest: the ones your stacker's rejection scheme missed (a very bright trail that pulled the median up, a trail that fell on a bright nebula edge where sigma thresholds are soft, meteors that are too short to look like outliers to a per-pixel rejection algorithm). Cleaning per-sub is strictly more conservative than trying to remove a trail from the final stack — you only touch the frames that have the problem.

2. Input and output folders

Two buttons at the top of the control column pick input and output folders. The button text updates to show the chosen folder's name once set; the full path is kept in QSettings and restored on next open. Both folders are tracked by a QFileSystemWatcher: when the OS reports a directory change (file added, removed, renamed) the matching tree view on the right refreshes automatically.

The tree views show every supported file in each folder:

Supported formats for load: PNG, TIFF (8/16/32-bit), FITS (any bit depth), XISF, and camera raws (CR2, NEF, ARW, DNG, RAF, ORF, RW2, PEF, JPG, JPEG). Output format matches the input extension — a FITS sub produces a FITS output, an XISF produces XISF with its original per-image metadata preserved, and so on. Formats SASpro's legacy saver can't write to directly default to FITS 32-bit float.

3. Full vs Luminance mode

The Satellite Removal Mode dropdown picks what the segmenter operates on:

Default is Full. Luminance is a good fallback when Full is over-correcting the chrominance of the surrounding sky (visible as a faint color cast where the trail was).

4. Sensitivity and the clip options

The segmenter's raw output is a soft confidence mask with values in [0, 1] — brighter where the model is more confident a pixel is on a trail. The Clipping Sensitivity slider (0.01-0.50, default 0.10) is the threshold applied to that mask:

m'[i,j] = m[i,j] \cdot \mathbf{1}[m[i,j] \geq s]

Mask values below the sensitivity threshold are zeroed out (treated as background); values at or above are kept. Lower sensitivity = more aggressive segmentation — the model catches dimmer trails but may also false-positive on bright star edges or sharp nebula structures. Higher sensitivity = more conservative; only the obvious trails are cleaned. 0.10 is a good default; drop to 0.05 for subtle trails on dim backgrounds; raise to 0.20 if you're seeing false positives on your data.

Two checkboxes modify what happens where the mask is non-zero after thresholding:

Skip Save if No Satellite Trail Detected is a batch-mode optimization. The segmenter reports a boolean detected flag alongside the mask; if the max of the thresholded mask is zero, nothing was found and this checkbox causes the file to be skipped entirely rather than written out as a bitwise-identical copy. Useful for processing a 500-sub session where only 20 subs actually have trails — you end up with 20 output files to review, not 500. The input tree still lists all files; only the output tree shows the subset that actually needed work.

Pre-batch sensitivity tuning. Before committing to a long batch run, use Process Single Image on one or two files you know have trails. Try sensitivity 0.10, inspect the output, nudge up or down until you catch the trails without visible false positives on stars or structure. Then run Batch with the same setting. Saves hours of "the batch finished but the sensitivity was wrong."

5. Delete Original After Saving

Delete Original Image After Saving is the most destructive option in the dialog and is treated accordingly. When checked and before any run begins, a confirmation dialog spells out exactly what will happen:

The dialog defaults to "No" and must be explicitly confirmed with "Yes" to proceed. Cancel on this confirmation aborts the run before any files are touched.

Delete-original safety: the only guard. SASpro checks that the input path and output path are not the same file (os.path.abspath comparison) before deleting. Everything else is up to you. If your output folder is the same as your input folder, the _satellited suffix produces a different filename and the original gets deleted. If you use delete-original with a bad sensitivity setting on a batch, you'll lose the originals of files that got over-aggressively "cleaned." Use it when you're confident, and preferably with the output folder on a different disk or in a different directory tree so the originals aren't gone forever if you ever want to re-run.

6. GPU acceleration and Compatibility Mode

The Use GPU Acceleration dropdown is a simple Yes/No. "Yes" picks the best available GPU backend (CUDA on NVIDIA, DirectML on Windows for Intel/AMD, MPS on Apple Silicon where available). "No" forces CPU — considerably slower, but useful for debugging or for running satellite cleanup in the background while the GPU is tied up with something else (stacking, denoise on the main Cosmic Clarity dialog, another AI task).

GPU Compatibility Mode is the fallback for problematic hardware — low-VRAM GPUs, older cards, certain Windows laptop configurations where the normal AI path crashes. Compatibility Mode uses a conservative inference path with reduced batching and no half-precision autocast. Slower, but survives where the default path fails. Toggle it on if the first batch run throws a GPU error or produces visibly corrupted output; leave it off otherwise.

7. Workflow recipes

Session live monitor (recommended for active imaging). Point your capture application at a folder. In SASpro, open Cosmic Clarity Satellite. Set Input folder to the capture folder, Output folder to a separate "cleaned" subfolder. Mode = Full, Sensitivity = 0.10, Clip Trail = on, Skip Save if None = on. Click Live Monitor. Each sub lands → gets segmented → gets cleaned (or skipped if nothing found) → appears in the output folder. End of session, your cleaned subs are already ready to stack.
Overnight batch on last night's data. After a session, point Input at last night's unprocessed subs folder. Pick an Output folder. Full mode, Sensitivity 0.10, Clip Trail on, Skip Save if None on. Batch Process. Comes back with just the trail-affected subs in the output folder. Replace those subs in your source folder before stacking.
Sensitivity tuning pass. Pick one or two subs with known trails. Process Single Image → File on Disk → pick the sub. Inspect the output. Adjust Sensitivity up or down. Repeat on the same file until the trail is cleaned without visible artifacts on stars. Then switch to Batch with that sensitivity.
Clean a single image already in SASpro. You have a view open and you spotted a trail. Open Cosmic Clarity Satellite. Click Process Single Image → Open View → pick the view. The result replaces the view's image via SASpro's normal document pipeline (undo-aware). No files written, no folders needed.
Delete-original cleanup for storage-constrained sessions. SSD is almost full. Set input and output to the same folder (saved subs land as name_satellited.ext alongside originals). Enable Delete Original. Confirm the warning. Batch Process. Originals get deleted as cleaned versions are saved; disk usage stays flat. Use with care.
Hands-off aggressive cleanup. Sensitivity 0.05, Full mode, Clip Trail off (use AI inpaint for smoother single-sub appearance). Fine for stacks where you want the individual subs to look clean on their own; may produce occasional false positives on bright stars, so inspect a few outputs before trusting the whole run.
Faint narrowband with low-SNR trails. Mode = Luminance (preserves chrominance on the dim nebula), Sensitivity = 0.08, Clip Trail = on. Narrowband data has low per-pixel SNR which can confuse Full-mode segmentation; luminance-only is more stable.

8. Credits

Model and training. Franklin Marek, SetiAstro — original neural network satellite trail segmenter, trained in-house on real deep-sky integration data with hand-labeled trail / no-trail examples spanning aircraft, satellites, meteors, and (false positive avoidance) bright stars, galaxy edges, nebula filaments, and diffraction spikes. Model file: satelliteRemovalAI4.pth.

SASpro integration. Dialog UI, three run modes (single / batch / live monitor), QFileSystemWatcher-driven tree view auto-refresh, per-file XISF metadata round-trip, delete-original safety confirmation and path-equality guard, GPU provider selection with Compatibility Mode fallback, progress reporting across the batch, and standard preview-dialog integration — all Franklin Marek as part of SetiAstro Suite Pro.

Runtime. PyTorch (pytorch.org) for neural network inference. SASpro's legacy image I/O layer handles format detection, raw camera demosaicing, and FITS/XISF/TIFF read/write.

Technical details

9.1. Segmenter output and sensitivity threshold

The segmenter outputs a soft confidence mask in the unit interval:

m \in [0, 1]^{H \times W}

Values near 1 indicate high confidence that a pixel is on a trail; values near 0 indicate background. The sensitivity threshold is a simple floor:

m'[i,j] = m[i,j] \cdot \mathbf{1}[m[i,j] \geq s]

where 1 is the indicator function. The thresholded mask m' drives the output: pixels where m' = 0 are left as the original source; pixels where m' > 0 are either zeroed (clip trail on) or replaced with an AI-interpolated inpaint (clip trail off).

9.2. Trail detection flag

The engine reports a boolean detected flag alongside the processed image:

\mathrm{detected} = (\max_{i,j} m'[i,j]) > 0

— true if any pixel survived the threshold. The Skip-Save-If-None checkbox tests this flag to decide whether to write the output file. The flag is also what the per-file log line reports ("Skip (no trail): filename" vs "Saved: filename").

9.3. Clip-trail output

When Clip Trail is on, the output is the source with masked pixels set to zero:

\mathrm{out}[i,j] = 0 \text{ where } m'[i,j] > 0

This is deterministic and visually obvious — downstream per-sub integration rejection schemes (sigma clipping, Winsorized, percentile) see pure zeros and reject them cleanly. The alternative (clip off) runs an AI inpaint over the masked region and composites:

\mathrm{out} = (1 - m') \cdot \mathrm{src} + m' \cdot \mathrm{inpaint}(\mathrm{src})

which gives smoother single-sub appearance but writes "real-looking" pixel values that may be harder for a stacker to reject if the segmentation was imperfect.

9.4. Full vs Luminance mode

Full mode runs the segmenter on the RGB input directly, producing a per-channel correction. Luminance mode first extracts a luminance channel using the standard Rec.709 weights:

Y = 0.2126 R + 0.7152 G + 0.0722 B

runs the segmenter on Y alone, and composites the result back as a luminance replacement with the original chrominance preserved:

\mathrm{out}_Y = f_\mathrm{sat}(Y),\;\; \mathrm{out}_{RGB} = (\mathrm{out}_Y / Y) \cdot \mathrm{src}_{RGB}

where f_sat is the trail-removal operation on luminance. Division is guarded against Y=0 (black pixels keep their RGB zeros). Luminance mode is ~3× faster than Full since only one channel is processed, and it preserves color in regions where the trail is primarily a brightness anomaly.

9.5. Live-monitor polling and set-based deduplication

Live Monitor is the Batch loop with a polling sleep at the bottom:

\Delta t = \max(50,\; 1000 \cdot \mathrm{poll\_seconds})

(milliseconds, default 1000ms = 1s). The thread maintains a _seen set of already-processed filenames; each poll pass computes todo = current_files - seen and processes only the new entries. Files already in the output folder (same stem + _satellited suffix) are logged "Exists, skipping" and marked done without re-processing — safe to restart the monitor against the same input folder without redundant work.

9.6. Delete-original path safety

Before unlinking an original, the engine checks:

\mathrm{abspath}(\mathrm{fp}_\mathrm{in}) \neq \mathrm{abspath}(\mathrm{fp}_\mathrm{out})

If the two paths resolve to the same file (input and output folder set to the same location, suffix stripping somehow produces the input name back, user manually set output path to collide with input), the delete is skipped and the original is preserved. This is the only protection against delete-with-same-path accidents — no undo trash, no "delete after 30 days" grace window, no SASpro-level recoverable deleted-items store. The warn callout in §5 covers the rest.

9.7. XISF metadata round-trip

XISF inputs carry per-image metadata (CFA layout, bayer pattern, instrument info, environmental data, calibration provenance) that stackers depend on. The load path extracts this as the xisf_meta field of the metadata dict; on save, SASpro passes it through to the writer as the image_meta parameter. If the metadata is a single dict rather than a list of dicts (XISF supports multi-image containers), it's wrapped in a one-element list before passing — the XISF writer expects a list. FITS metadata (headers) rides through on the standard header pathway independently; TIFF and PNG have no equivalent per-image metadata so the fields are passed as None.

9.8. Progress reporting

Per-batch progress is reported as:

\mathrm{frac} = \mathrm{done} / \mathrm{total}

where done is the count of files already processed (or skipped) in the current pass and total is the pass's todo-list size. In Live Monitor mode the total resets each poll pass; the wait dialog shows "N / M files" during active processing and "0 / 0" during idle polling. Single-image mode uses a native QProgressDialog instead of the batch wait dialog, with the engine's per-tile progress callback driving the bar directly.

9.9. Normalization and bounds

Every image loaded is normalized to float32 in [0, 1] before inference:

x_{\mathrm{clip}} = \mathrm{clip}(x,\; 0,\; 1)

The clip bounds the input to the model's trained range (uint16 inputs scale by 1/65535 first); the output is clipped again before save to guarantee no out-of-range values reach disk. Saves use SASpro's standard legacy writer with 32-bit float as the default bit depth for FITS and TIFF; PNG and JPEG fall back to the writer's own 8-bit encode.

9.10. Settings persistence

Satellite dialog settings persist under the satellite/ QSettings prefix:

Settings save on closeEvent and on every change via the dialog's save hook; folders are also saved after each successful chooser interaction so a crash mid-session preserves the folder selection for next launch.