The pipeline
What Nebula Stacker actually does
Stacking is treated as one joint inverse problem rather than a sequence of independent fixes, and the order below is the order it runs in — each phase using what the last one measured. Nothing here is a preset.
Calibration and the noise model
Before anything is combined, the program works out what your sensor does — so that later steps weigh each pixel by how much it can be trusted rather than treating them alike.
Bias frames are split by their own median level and each frame gets the master below it. A bias frame measures the readout at one gain, and averaging two ISOs into one master leaves a pedestal in every frame that the flat then divides and prints its own vignetting onto.
Gain in electrons per ADU, fitted across signal levels. Read noise always comes from the bias frames rather than the curve's intercept — extrapolating from tens of thousands of ADU down to tens gets it wrong by threefold.
A read-noise map turned into 1/variance weights. A pixel that flickers counts for less, continuously — no bad-pixel verdict, no threshold to tune.
Found from the dither: a defect is fixed on the detector, a star is fixed on the sky, and the frames move. A hot pixel's excess is subtracted; a dead one has its weight set to zero, because no arithmetic recovers a signal that was never there.
The flat field measured from your light frames themselves — same optics, same dust, same moment — using the registration to know where the target is rather than inferring it. Flat frames become optional: a stack with none comes out no worse than one with them.
Variance-stabilising, so that the comparison used for outliers means the same thing at the bright end as at the faint end.
Separating the sky from the detector
Light pollution is added to your frames; vignetting multiplies them. Telling the two apart is what the dither pays for, and the commonest way for a stacker to eat a galaxy is to get it wrong.
The background is never fitted to a frame. It is fitted to what is left of a frame once the current sky estimate has been reprojected into that frame's detector coordinates and subtracted — so real nebulosity is already in the estimate, is therefore not in the residual, and a low-order surface cannot absorb it.
Skyglow has a spectrum, so whatever shape it makes it makes the same shape in red, green and blue. Ten degrees of freedom instead of eighteen, and the eight given up are exactly the ones a background model uses to eat a target. A nebula can no longer be absorbed unless it is the colour of the streetlights — and Hα is not.
Skyglow changes over minutes rather than between subs, so the fits are smoothed in capture order and only the surface's shape is subtracted — its level is not separable from the sky's own brightness.
Uses the axis a narrow dither cannot: time. Regressing each cell against the frame's own sky level over a night separates what is there at zero sky — amp glow, a light leak — from what scales with it, which is the sky's own gradient.
Coaddition
How the frames are actually combined. Two estimators, and the frames choose which — a decision the program makes from your data and then reports.
Zackay & Ofek's form: each frame weighted per spatial frequency by what its own seeing and noise let it contribute there, then deconvolved and reconvolved to a stated target. With frames that are alike it reduces exactly to the plain mean, so it can never do worse.
Where the frames are undersampled, the mosaic is stacked at the sensor's own grid and demosaiced once, at the end. A superpixel demosaic throws away half the resolution before the first frame is placed. Measured: a quarter tighter stars and eighty per cent more of them resolved.
A trailed frame is not a blurred frame — it is sharp across the trail and smeared along it. Fitting an ellipse rather than a circle undoes the smear in the direction it actually runs, so a marginal sub still contributes what it has.
Deliberate. Interpolating would correlate neighbouring pixels and break the noise statistics every other measurement here depends on — so a sample lands on one output pixel or on none.
The fallback estimator: an à trous decomposition weighting each frame separately at each scale. What it scales is the frame's deviation from the estimate, which averages to zero over any subset — so masked pixels do not skew it.
Outliers, as objects
Sigma clipping asks each pixel in isolation whether it looks odd. At three sigma one pixel in 370 is odd by chance, and rejecting those is exactly the mottling it was meant to prevent.
A Hough transform over the exceedance map finds the line, its width is measured from the seed-rate profile across it, and the whole feature is masked. Searched on a coarse grid and verified at full resolution, because the thresholds mean what they were measured at.
Connected components, dilated and masked whole. Scattered single pixels are left alone deliberately.
A line is only believed if the seeds along it are four times denser than the seeds beside it. A Hough transform finds lines in anything dense enough; a satellite is a line with quiet sky either side.
“Three sigma” on four frames is not one in 370 — it is one in seventeen, because the spread was estimated from those same four. The threshold is the t quantile for the number of frames actually there.
Registration
Aligning the frames, and putting them on a common photometric scale — which on a real night is worth more than everything else combined.
The reference frame is solved against a star catalogue once; every other frame is matched against the reference by quads, which is far cheaper and far more accurate than solving each one blind.
A similarity transform has four numbers and a real field distorts by several pixels at the corners. A third-order polynomial fits what the similarity could not explain — 0.97 px rms down to 0.12 px on real subs. Refused unless it beats doing nothing.
Red, green and blue are refracted by different amounts and arrive displaced. The offsets are measured from the frame's own stars and smoothed along the session, because dispersion follows airmass over tens of minutes.
Every frame put on the reference's scale by the median flux ratio over matched stars — and only the light above the sky is divided by transparency, because the skyglow was there whatever the weather. On a night running 0.82× to 1.02× this took star signal-to-noise from 59 to 115.
Mixed exposures
Long subs for the faint structure, short ones for the cores that burnt out — combined without a blending stage.
A sample at full scale is not a measurement: the well filled and the count stopped, so it says “at least this much”. Those samples are left out and the shorter subs say what is inside the core. Each pixel uses whatever actually measured it.
The question is asked of the raw reading, before calibration touches it — “the count stopped” is a statement about the ADC, and nothing a bias subtraction does to the number afterwards can be part of it.
A 90-second sub among 600-second ones has a third of the stars because it is a 90-second sub. One quality baseline per exposure length, or every short frame gets set aside as cloud.
Colour
Three overlapping filters over one sensor, calibrated against a catalogue rather than against taste.
The field is plate-solved, catalogue stars are matched to measured ones, and a robust line through BP − RP separates the instrument from the sky. The convention: a solar-colour star renders neutral.
G1 and G2 sit on opposite diagonals of the Bayer tile and are not the same detector. Averaging them is what produces the maze artefact conventional debayering is famous for. They are carried separately and balanced — measured at 0.088 % apart — so the artefact never exists rather than being filtered out.
Colour varies smoothly across almost all astronomical structure and the eye has far less acuity for it. The ratios are averaged and the Rec. 709 luminance put back untouched — not the plain sum, which lets a star's brightness drift while the arithmetic looks preserved.
A smooth multiplicative colour cast across the field, fitted from stars whose catalogue colours are known. On a well-flatted field it measures the gradient as insignificant and declines — which is a measurement of your optics, not a failure.
Measurement and reporting
Every number the result screen shows is measured on your delivered pixels. Where something could not be measured safely, the program says so instead of guessing.
Width at half maximum, interpolated between pixels and reported per region — a field sharp in the middle and soft at the corners has no single width. Roundness from second moments, because a smeared star has almost the same width as a round one.
Noise from first differences between adjacent pixels, which cancels gradients and stars. Separate measures for texture at 32 px and real structure at 128 px, because a correction can improve every per-pixel number while printing a visible pattern.
Tilt and field curvature fitted separately, because they want opposite fixes and one “the corners are soft” number points at the wrong screw half the time. Below the frame-to-frame wander, the field is reported even rather than a fault invented.
Every line names a number from your run. Generic good practice is the same list for everybody and is worth nothing.