Removes broadband continuum signal (stars and reflection light) from narrowband frames, so that only true line-emission from the nebula remains. SASpro's implementation calibrates each filter against its matching continuum (or against an OSC channel) with background neutralization, MAD-matched red/green rescaling, and star-based white balance, then lets you tune the subtraction strength Q interactively per filter before committing the full-resolution result.
Each slot has a starry row (used for the WB fit) and a +starless row directly beneath it (optional — receives the same calibration recipe but without star detection). Two load buttons per row:
Three groups of inputs:
| Slot | What to load | Paired continuum |
|---|---|---|
| Ha | Hα narrowband (mono) | Red (or OSC's R channel) |
| SII | SII narrowband (mono) | Red (or OSC's R channel) |
| OIII | OIII narrowband (mono) | Green (or OSC's G channel) |
| HaO3 | Dual-band composite, 3-channel (R=Hα, G=OIII) | auto-decomposed, see §2.6 |
| S2O3 | Dual-band composite, 3-channel (R=SII, G=OIII) | auto-decomposed, see §2.6 |
| Slot | What to load |
|---|---|
| Red | Red broadband (mono) — used as the continuum for Hα and SII. |
| Green | Green broadband (mono) — used as the continuum for OIII. |
| OSC | One-shot colour broadband (3-channel). Replaces Red and Green together: R-channel becomes the Hα/SII continuum, G-channel becomes the OIII continuum. Loading an OSC after a mono Red/Green keeps the mono choice; the selection logic prefers the explicit mono slot when present. |
target_median = 0.25. When off, the output is linear regardless of the “Output linear only” checkbox. When on, three sub-options:
0.7×median after stretch for a cleaner background. Default on; uncheck to preserve faint signal.median − σ. Default on, preserves faint background signal.Clicking Execute kicks off one calibration thread per loaded filter (background neutralization, red/green matching, star-based WB fit, downsampled preview). When all filters have calibrated, the Interactive Q Preview dialog opens:
When the final subtracts finish, each filter becomes a new document in SASpro titled <filter>_ContSub (and <filter> (starless)_ContSub if a starless partner was supplied). The original FITS header travels with the result; bit depth is 32-bit float.
Enabled after the first result lands. Opens a scrollable grid, one card per filter, each with two 256×256 thumbnails:
Click either thumbnail to open the Detail View dialog — zoomable, with Autostretch and Push to New Document buttons so you can hand the diagnostic image onwards for inspection.
Dumps every loaded slot and resets labels. The processing options stay as you set them.
The subtraction pipeline, per filter, in order.
Each filter is processed as its own three-channel RGB stack with R = NB, G = continuum, B = continuum (B is a copy of G so the standard colour tools work unchanged). The pipeline runs in two phases separated by the Q Preview dialog:
Starless partners (optional per filter) are run through the same recipe their starry partner produced — no independent WB fit — so the two images stay perfectly in sync and the stars cancel to the same residual in both.
Finds the darkest reasonable patch in the frame and lifts each colour channel so that patch becomes neutral grey. 200 random 25×25 boxes are placed and iteratively migrated toward darker neighbours over 25 iterations (nine-cell gradient descent, picking the darkest neighbour each step). The darkest surviving box becomes the background reference; per-channel pedestals are
A second pass compensates for red-stronger-than-green/blue imbalance (sky-glow bias) by lifting G and B toward the red reference:
applied to the green and blue channels only (c ∈ {G, B}); the red reference stays unchanged.
The image is then clip(I + p, 0, 1).
Before white balance, the NB (red) channel is linearly rescaled so its central tendency and spread match the continuum (green) channel. This gives the subsequent WB fit a scale-free problem to work with. Using mean absolute deviation
the red channel is transformed to
so median(R') = median(G) and MAD(R') = MAD(G). Note that this is the mean absolute deviation, not the robust median-based MAD — the mean version is cheaper and the subsequent WB fit is robust enough to absorb any residual mismatch.
The classical move for NB continuum subtraction: stars have smooth continuum spectra, so after true white balance a star should have equal NB and broadband flux (ignoring narrowband-leak lines like [NII] in the Hα filter). Measuring the actual NB vs broadband flux across many detected stars gives a per-channel linear transform
fitted independently for each channel c ∈ {R, G, B}.
fitted by least squares against the pre- and post-WB sample pairs for each channel:
Star detection uses a SEP-based detector at the user-set σ threshold; a cache lets subsequent runs reuse the detection on the same frame. Both the fit coefficients and the detected-star overlay are stored in the recipe dict and surfaced in WB Diagnostics (§1 — WB Diagnostics).
Once calibration is done and you've chosen Q, the per-pixel subtraction is:
or in the internal RGB representation,
then clipped to [0,1]. Subtracting G − median(G) (rather than G directly) means a perfectly dark continuum pixel contributes nothing, and only the pixels where continuum is above its own background are subtracted away. After star-based WB has set the per-pixel scale correctly, Q = 1 is the mathematically pure value — stars cancel exactly, line-emission survives untouched. Lower Q leaves some star residual (useful if the WB fit was marginal); higher Q over-subtracts (produces dark halos around stars).
The same recipe is then re-applied to the starless partner (if loaded) with the same Q, so NB-pure and NB-pure-starless share one calibration.
When a 3-channel composite is loaded into HaO3 or S2O3, SASpro splits it in-place:
For an HaO3 composite with channels (R, G, B):
For an S2O3 composite:
The split channels populate the Ha / SII / OIII slots as if they'd been loaded there directly. When both HaO3 and S2O3 are loaded, their two OIII channels are averaged into the OIII slot:
and the slot label updates to OIII from HaO3+S2O3 so you can see what's actually going into the subtraction. A manually loaded OIII overrides this; the composite-average logic only touches the slot while it's being auto-filled from composites. Starless composites decompose into starless slots the same way, keeping the two paths separate.
When Auto-stretch is on and “Output linear only” is off, the linear subtracted result is finished with:
target_median = 0.25 (shared stretch core with the rest of SASpro; see Statistical Stretch doc for the stretch function itself).apply_curves_adjustment helper (same curve engine as the Curves tool, run with curves_boost = 0.5).“No black clip” is honoured throughout — the stretch uses the image minimum as the black point rather than median − σ, which protects very faint diffuse structure that would otherwise be clipped away.
When enabled, denoising runs on the linear subtracted image, after §2.5 and before §2.7. SASpro calls Cosmic Clarity headless with:
Denoising the linear data is important for continuum subtraction: after subtraction, the sky background should sit near zero, and any residual noise there turns into visible mottling after stretch. Doing the denoise before the stretch (while noise statistics are still well-behaved and Gaussian-like) gives a much cleaner final result than denoising afterwards.