RGB Combination

Build a single RGB document from three mono channels — either from open views in the current session or from files on disk. Classical workflow for RGB/LRGB/narrowband assembly: process each filter's stack as mono (calibration, registration, denoise, stretch if you want pre-combine stretches) and bring the three together here. Always creates a new document; nothing is written to the source channels.

1. Mode selector

Two radio buttons at the top of the dialog pick where the three channels come from:

Only one mode is active at a time — the inactive mode's widgets are greyed out so there's no ambiguity about which inputs will be used.

2. Views mode

Three combo boxes (Red / Green / Blue), each showing every open document by its window title.

Automatic channel guessing

When the dialog opens with at least three documents available, SASpro scores every title against the three channels and pre-selects the best match for each dropdown. Scoring looks at the title in lowercase and awards points for:

The best-scoring title is pre-selected; ties fall to the first match in the dropdown order. If no title scores above zero for a channel, the first document is chosen as a neutral default and you're expected to pick manually. The heuristic is designed to Just Work on filenames like NGC7000_Ha.fits / NGC7000_OIII.fits / NGC7000_SII.fits or the more literal M31_red / M31_green / M31_blue, but it never locks a choice — the dropdowns are always user-overridable.

3. Files mode

Each of the three Load… buttons opens an OS file dialog filtered to common astronomy formats. The chosen filename is shown next to its button; nothing is read from disk until Combine is pressed. Multi-channel files are supported — see § 6.1 for what happens to their channels.

4. Combine

Reads the three channels, verifies dimensions, stacks them into a new RGB document named either RGB_Combined (views mode) or RGB_<red-file-stem> (files mode), and opens a subwindow for it. The source documents and files are left untouched.

WCS inheritance

In views mode, the new document inherits a World Coordinate System from the first donor among the three that carries one, in the order Green → Red → Blue. Green is tried first because it sits in the middle of the visible spectrum and is the usual astrometric calibration channel in LRGB rigs; the other two are tried only if green has no WCS. In files mode no WCS is inherited — the source documents don't exist in-session to pull headers from. If you want WCS on a files-mode combine, open the files as documents first, then use views mode.

Shape requirement

All three channels must have identical dimensions. A mismatched set raises a message dialog with the mismatch and no new document is created; align or crop upstream and retry.

5. Technical details

Everything happens on float32 [0, 1]. The combine is a plain stack-along-axis-2; the interesting work is in the input normalisation and the channel-match scoring.

5.1 Mono extraction

Each selected input (view image or loaded file) passes through _mono_from_any, which produces a 2-D float32 [0, 1] array:

5.2 Normalisation

_to_f01 coerces every input to float32 [0, 1] without assumptions about where the data came from:

5.3 Channel-match scoring

Each candidate title gets a per-channel score computed from case-folded regex matches. The scoring vector by channel is:

PatternRGB
Full colour word (red/green/blue) +10+10+10
Separator-bounded letter (_r_ etc.) +8+8+8
Suffix / end-of-title letter +7+7+7
Ha emission line +6——
SII emission line +5——
OIII emission line —+5+4
Conflicting colour word −10−10−10
Conflicting single-letter code −5−5−5

Separator matching uses the character class [_\-\s\.] for “letter boundary”, so dots in filenames behave the same as underscores or hyphens. The three channel scorers run independently per title, and the title with the highest positive score wins its dropdown. Scores of zero or less leave the dropdown at index 0 as a neutral default — which is why, on a fresh session with three generically-named documents, you'll sometimes see all three channels defaulting to the first document; that's by design, not a bug.

5.4 Stack and clip

Once R, G, B are three identically-shaped 2-D float32 arrays:

RGB[y, x, 0] = R[y, x] RGB[y, x, 1] = G[y, x] RGB[y, x, 2] = B[y, x]

via np.stack([r, g, b], axis=2), then clipped once more to [0, 1] as a belt-and-braces guard against anything the per-channel normalisation might have missed in edge cases (NaN-dominated frames, etc.).

5.5 Document creation and WCS transfer

The result is handed to the document manager via whichever of open_array, open_numpy, or create_document is available, with metadata step_name = "RGB Combination" and the title derived from the mode (as in § 4). The main window's WCS helpers (_extract_wcs_dict, _apply_wcs_dict_to_doc) are then called in the G → R → B donor order until one of them yields a usable WCS, which is copied onto the new document before its subwindow is spawned. If no donor has a WCS, the new document carries none — a plate-solve can be run on it afterwards from any of SASpro's astrometry tools.