Continuum Subtraction

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.

Workflow
Load NB + matching continuum → Execute → calibration runs per filter in parallel → Q Preview dialog opens → tune Q per filter against live preview → Accept → final subtraction + optional denoise + optional stretch → results open as new documents.

1. Using the tool

Loading images

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:

Narrowband Filters

SlotWhat to loadPaired continuum
HaHα narrowband (mono)Red (or OSC's R channel)
SIISII narrowband (mono)Red (or OSC's R channel)
OIIIOIII narrowband (mono)Green (or OSC's G channel)
HaO3Dual-band composite, 3-channel (R=Hα, G=OIII)auto-decomposed, see §2.6
S2O3Dual-band composite, 3-channel (R=SII, G=OIII)auto-decomposed, see §2.6

Continuum Sources

SlotWhat to load
RedRed broadband (mono) — used as the continuum for Hα and SII.
GreenGreen broadband (mono) — used as the continuum for OIII.
OSCOne-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.
You need at least one NB slot plus its matching continuum (or an OSC) for Execute to do anything. Load as many filters as you have — each one is calibrated and shown in the Q preview separately.

Processing Options

Execute, then the Q Preview dialog

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:

Tuning Q: stars should become invisible when Q is right. If stars go dark (black pinholes) you've over-subtracted — reduce Q. If stars remain bright you've under-subtracted — increase Q. Nebular structure should sit around 0 in empty sky and above 0 where there's real emission. The preview downsamples to a max long axis of 1024 px for responsiveness; the final subtraction runs at full resolution.

Results

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.

WB Diagnostics

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.

Clear Images

Dumps every loaded slot and resets labels. The processing options stay as you set them.

2. Technical details

The subtraction pipeline, per filter, in order.

2.1 Pipeline overview

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:

Phase A — calibration (one QThread per filter):
  background neutralization → MAD-matched R↔G rescale → star-based WB fit → downsampled preview + recipe stored
Phase B — final subtract (one QThread per filter, after Accept):
  apply recipe at full-res → linear subtract with the chosen Q → optional denoise → optional stretch → emit result

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.

2.2 Background neutralization

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

p_c = \max\!\left(0,\;\mathrm{median}(I_c) - \mathrm{bg}_c\right)

A second pass compensates for red-stronger-than-green/blue imbalance (sky-glow bias) by lifting G and B toward the red reference:

p_c \to p_c + \max(0,\;\mathrm{bg}_R - \mathrm{bg}_c)

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).

2.3 MAD-matched red/green rescale

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

\mathrm{MAD}_{\mu}(x) = \mathrm{mean}(|x - \mathrm{mean}(x)|)

the red channel is transformed to

R' = \frac{\mathrm{MAD}_{\mu}(G)}{\mathrm{MAD}_{\mu}(R)}\,R + \left(\mathrm{median}(G) - \frac{\mathrm{MAD}_{\mu}(G)}{\mathrm{MAD}_{\mu}(R)}\,\mathrm{median}(R)\right)

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.

2.4 Star-based white balance

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

c' = a_c\,c + b_c

fitted independently for each channel c ∈ {R, G, B}.

fitted by least squares against the pre- and post-WB sample pairs for each channel:

(a_c,b_c) = \arg\min_{a,b}\sum_i \left(a\,x_{c,i} + b - y_{c,i}\right)^2

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).

2.5 Linear subtraction

Once calibration is done and you've chosen Q, the per-pixel subtraction is:

\mathrm{NB}_{\mathrm{pure}} = \mathrm{NB} - Q\,(C - \mathrm{median}(C))

or in the internal RGB representation,

R' = R - Q\,(G - \mathrm{median}(G))

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.

2.6 Composite OSC decomposition (HaO3, S2O3)

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):

\mathrm{Ha} \leftarrow R,\;\;\;\mathrm{OIII} \leftarrow G

For an S2O3 composite:

\mathrm{SII} \leftarrow R,\;\;\;\mathrm{OIII} \leftarrow G

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:

\mathrm{OIII}_{\mathrm{avg}} = \frac{1}{N}\sum_{k=1}^{N} G_k

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.

2.7 Non-linear finalization

When Auto-stretch is on and “Output linear only” is off, the linear subtracted result is finished with:

  1. Color stretch to target_median = 0.25 (shared stretch core with the rest of SASpro; see Statistical Stretch doc for the stretch function itself).
  2. Median background subtract (optional):
    S' = S - 0.7\,\mathrm{median}(S)
    then clip to [0,1]. The 0.7 coefficient is empirically chosen to pull background down without crushing faint signal.
  3. Curves boost (optional) — a gentle S-curve applied through the shared 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.

2.8 Cosmic Clarity denoise

When enabled, denoising runs on the linear subtracted image, after §2.5 and before §2.7. SASpro calls Cosmic Clarity headless with:

mode = denoise denoise_luma = strength (slider value, 0.0–1.0) denoise_color = strength denoise_mode = full chunk_size = 256 overlap = 64 gpu = (checkbox)

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.

Credits. Modern narrowband continuum subtraction for amateur astroimaging was pioneered by Vincent Peris, Edoardo Radice, Charles Hagen, Franklin Marek (SetiAstro) and others — through tooling, workshops and published methods that established the star-based white-balance approach as the standard way to recover line-emission from narrowband frames contaminated by broadband sources. This tool is SASpro's take on that lineage.