Stretch
Convert linear data -- where almost all real signal sits near zero and is invisible on a normal display -- into a non-linear image a human can actually see, without crushing the sky, clipping stars, or hiding the shape of the stretch curve's own tradeoffs.
schema 1 · revision 1Recognize it
- The linear image displays as almost entirely black except star cores; faint structure is present in the data but not visible without a tone curve.
- A naive linear stretch either leaves the image too dark to judge or blows out the brightest cores before faint structure becomes visible.
Intended output
A non-linear image with a dark, low sky background, visible faint structure (galaxy arms, dust lanes, nebulosity), and star cores that are not hard-clipped.
Required input state
- Linear, unstretched data, after deconvolution and denoise (and star correction, on workflows that run it) -- late in the pipeline, immediately before background-neutralize/color-boost operate on the now-visible tonal range.
What NOVA does
NOVA's ontology exposes six real stretch engines behind 13 selectable parameter presets: PixInsight MultiscaleAdaptiveStretch (pi_mas -- M66's recorded path), SASpro Statistical Stretch (stat_default/stat_bright/stat_globular), SASpro GHS Stretch (ghs_default/ghs_galaxy), and three NOVA-original engines with no external tool behind them: stf_stretch (a from-scratch reimplementation of the STF tone-curve concept, presets stf_galaxy/stf_nebula), veralux_stretch (an original arcsinh-based design with auto-detected symmetry point, presets veralux_default/colorful/globular), and smart_stretch, which profiles the image's dynamic range and star fraction and adaptively selects among STF/veralux/GHS/stat rather than running one fixed engine.
Use when
- Always, once linear processing (calibration, background, color, deconvolution, denoise) is complete -- this is the step that makes the image viewable at all.
Skip when
- The input is already non-linear (re-stretching a stretched image compounds tone curves and is a distinct, deliberate operation, not this step).
Limits
- This is the single most contested, aesthetically-loaded step in the whole pipeline -- 'correct' output depends on target type, sky darkness, and taste, not just physics. Treat any single stretch as a judgment call, not a ground truth.
- M66's recorded run validates exactly one engine (PixInsight MultiscaleAdaptiveStretch). NOVA has six real, code-confirmed stretch engines total; the other five are real alternatives it can select for other targets, not M66-validated.
- Different engines are mathematically unrelated -- statistical (percentile-based), generalized hyperbolic, arcsinh, and multiscale-adaptive curves. A similar-sounding parameter value on two engines (e.g. a 'target' near 0.08-0.15) does not imply a similar result; only the engine and its own documented math define the curve.
- stf_stretch, veralux_stretch, and the adaptive selector smart_stretch are NOVA-original code with no `setiastro` import and no PixInsight or SASpro GUI equivalent. veralux_stretch independently reimplements a real, separately installed Siril Python script named Veralux -- prefer that real script (Siril tab) as the reference path; Siril's native Asinh Stretch remains a fallback approximation when the actual script isn't installed. stf_stretch and smart_stretch still have no manual path in any tool.
- Irreversible: clipped highlights and crushed shadows from an aggressive stretch cannot be recovered from the output alone; the input's actual dynamic range sets the ceiling on what any engine can safely show.
Scientific and aesthetic notes
- Jeff's own stated preference is galaxies darker and higher-contrast than a generic 'bright and colorful' default -- a stretch that looks technically correct can still be the wrong aesthetic call for a given target.
- smart_stretch's adaptive engine selection is itself a real NOVA design decision, not a documentation gap: for some targets the 'right' engine genuinely depends on measured dynamic range and star density, not a fixed per-target-type default.
- The historical MAS parameters recorded from M66 are the module's own installed defaults (version 1.1.1.0), not values NOVA computed or tuned for this image -- the workflow created the process and ran it with zero overrides.
Evidence and measurements
Cross-tool matrix
| Tool | Equivalence | Expected result | Evidence |
|---|---|---|---|
| nova | Exact replay | A non-linear image with sky near-black, visible faint structure, and unclipped star cores. | nova-stretch-source, nova-m66-run-1.24.7 |
| pixinsight | Exact replay | Full-array median ~0.085, p99 ~0.473, max ~0.936 on M66's linear starless input -- deterministic (byte-identical output across repeated runs on the same input). | m66-manual-verification, nova-stretch-source |
| siril | Same engine, adapted host | A statistically-targeted stretch with the sky near the target median and negligible hard clipping. | m66-manual-verification |
| siril | Algorithmically equivalent | An arcsinh-based stretch from the same named script family NOVA's veralux_stretch reimplements, closer to NOVA's engine than the native Asinh Stretch fallback. | jeff-siril-veralux-note |
| siril | Functional alternative | A workable stretch using Siril's own native tools; not a reproduction of any specific NOVA engine's exact curve. | siril-native-stretch-manual |
| siril | Conceptual substitute | A dark-sky, arcsinh-shaped stretch broadly similar in character to Veralux, without matching its exact curve, color handling, or automatic background detection. | siril-native-stretch-manual |
| saspro | Same engine, adapted host | Sky lands near the chosen target median with linked-channel color preserved and a mild curves-boost S-curve applied. | saspro-source-1.18.0, nova-stretch-source |
| saspro | Same engine, adapted host | A hyperbolic-curve stretch with the pivot anchored near the sky level. | saspro-source-1.18.0, nova-stretch-source |
NOVA Python pipeline workflow 1.23.0 (M66 run); ontology current
- Confirm which of the six engines the active workflow selects before assuming MAS (M66's engine) is the general default -- it is one of six, not the only one.
- For stf_stretch or smart_stretch, do not look for a manual reproduction path in PixInsight/Siril/SASpro; none exists for these NOVA-original engines. Judge the output on its own measurements instead.
- For veralux_stretch, prefer the real Veralux Siril script (see the Siril tab) -- the same named algorithm, independently reimplemented -- over the native Asinh Stretch fallback if the actual script is installed.
- For stat_stretch/ghs_stretch/mas, the tool-specific tabs below give the real manual reproduction path.
Controls and starting ranges
- M66 recorded engine
- pi_mas -- PixInsight MultiscaleAdaptiveStretch, module defaults, no override
- other selectable engines
- stat_stretch, ghs_stretch, stf_stretch, veralux_stretch, smart_stretch
- NOVA-original, no manual equivalent anywhere
- stf_stretch, smart_stretch
- NOVA-original, real Siril script counterpart
- veralux_stretch -- Siril's own Veralux script, algorithmically equivalent; native Asinh Stretch is only the fallback
Mask behavior: Engine-specific; MAS has an internal lightness mask on its color-saturation stage (see the PixInsight tab).
Failure modes
- Presenting M66's MAS result as NOVA's one and only stretch behavior.
- Assuming stf_stretch or smart_stretch has a PixInsight/Siril/SASpro equivalent.
- Reaching for Siril's native Asinh Stretch fallback when the real Veralux script is actually installed and available.
- Presenting NOVA's veralux_stretch and the Siril Veralux script as byte-identical just because they share a name and algorithm -- independent implementations, algorithmically equivalent, not exact replay.
Recovery
- Revert to the linear input and select a different engine/preset for the target's actual dynamic range.
PixInsight MultiscaleAdaptiveStretch (MAS) MultiscaleAdaptiveStretch module 1.1.1.0
- Create a MultiscaleAdaptiveStretch instance and run it on the full linear starless image -- not a partial preview; Contrast Recovery does not permit partial-preview execution.
- M66's run applied every module default with zero parameter overrides; only override noiseThreshold/clippingFraction if you have a specific reason to.
- Inspect the whole-image statistics after; they describe the whole array, not a claim that the empty-sky region specifically landed at the target background.
Controls and starting ranges
- Target Background
- 0.150 (module default)
- Aggressiveness
- 0.70 (module default)
- Dynamic range compression
- 0.40 (module default)
- Background Reference
- disabled (module default)
- Contrast Recovery
- enabled, scale separation 1024px, intensity 1.00 (module defaults)
- Color Saturation
- enabled, Amount 0.75, Boost 0.50, Lightness mask enabled (module defaults)
Mask behavior: MAS's own internal Lightness mask restricts its color-saturation stage by luminance; this is not an externally-applied PixInsight mask.
Failure modes
- Substituting manually-tuned values (e.g. Target Background 0.095, Aggressiveness 0.80) and calling the result an exact NOVA reproduction -- those are Jeff's own experimental settings, not what the pipeline ran.
- Running Contrast Recovery on a partial preview, which the module does not support.
Recovery
- Reset to module defaults and re-run on the full starless image.
Seti Astro Statistical Stretch via Siril's Python integration Seti Astro Statistical Stretch integration v3.1.2, verified in Siril 1.4.4
- Open the licensed Seti Astro Statistical Stretch script on the linear image.
- Set the target median and black-point sigma, enable Linked Stretch and Normalize.
- Apply the curves-boost pass at the recorded strength; check the reported clip percentage before accepting.
Controls and starting ranges
- M66 verified
- Target median 0.15; Black point sigma 5.00; No black clipping, Linked Stretch, Normalize all enabled; HDR Highlight Compress disabled; Stretch luminance only disabled; Apply curves boost enabled at strength 0.50
- M66 result
- preview clip report 1 of 1,352,337 pixels (0.0001%)
Mask behavior: Not demonstrated; operates on the full image.
Failure modes
- Treating this as a stock Siril feature -- it is a separately licensed external integration, not bundled with Siril.
Recovery
- Undo and re-run with a lower target median or higher black-point sigma if the sky lifts too far.
Veralux via Siril's Python integration separately installed Python script; exact version not independently confirmed in this repo
- Open the Veralux script from Siril's Python scripts on the linear image -- a separately installed script, not a stock Siril feature, the same pattern as the Seti Astro Statistical Stretch integration above.
- This is the real, named script NOVA's veralux_stretch independently reimplements in Python -- prefer this over the native Asinh Stretch fallback below when it's installed, since it shares the actual algorithm rather than only the general arcsinh math.
- Record the exact menu path, script version, and every setting used; none of that is independently confirmed in this repository yet.
Controls and starting ranges
- availability
- Jeff-confirmed installed and available; exact menu path, version, and default parameters not yet independently verified in this repo
Mask behavior: Not independently confirmed in this repo.
Failure modes
- Treating this as a stock Siril feature rather than a separately installed script.
- Assuming NOVA's independently-coded veralux_stretch reproduces this script byte-for-byte just because they share a name and algorithm family -- same-named algorithm, independent implementations.
Recovery
- Fall back to native Asinh Stretch (below) if the script isn't installed.
Native Generalized Hyperbolic Stretch / Histogram Transformation 1.4.4
- Use as a no-extra-cost native alternative when the Seti Astro integration isn't installed.
- For GHS: set the Symmetry point just above the background, raise D (stretch intensity) and b (local intensity) to lift signal without blowing the core.
- Autostretch (the eyeball icon) is a fast preview, not a final result.
Controls and starting ranges
- GHS starting point
- Symmetry point near background level; no fixed D/b range established
Mask behavior: Not demonstrated.
Failure modes
- Presenting a native GHS/HT result as equivalent to NOVA's MAS, Statistical Stretch, or any NOVA-original engine.
Recovery
- Undo and adjust the symmetry point or stretch intensity.
Native Asinh Stretch (fallback if the Veralux script isn't installed) 1.4.4
- Use only as a no-extra-cost fallback when the actual Veralux script (above) isn't installed -- both are arcsinh-based, but this is Siril's own separate native tool, a conceptual approximation rather than the same algorithm.
- Open Image Processing > Asinh Stretch on the linear image; its two controls are stretch factor and black point.
- Sample the empty sky first and set the black point from that measurement, mirroring Veralux's own auto-detected symmetry point, before raising the stretch factor.
- Increase the stretch factor gradually and check star cores and color saturation at each step; Siril's default RGB blend clipping mode does its own luminance-based color blending during the stretch, but it has no adjustable equivalent to Veralux's color_grip parameter or its shadow-convergence damping.
Controls and starting ranges
- black point
- set from a measured empty-sky sample, not left at a default; no fixed value established
- stretch factor
- no fixed value established; raise gradually and inspect
- not reproduced here
- Veralux's adjustable color_grip parameter and shadow-convergence damping have no Asinh Stretch equivalent; Siril's own default RGB blend clipping mode blends luminance and color differently and isn't a substitute
Mask behavior: Not demonstrated.
Failure modes
- Leaving the black point at Siril's default instead of sampling the actual sky level.
- Presenting this result as a reproduction of Veralux rather than an approximation of the same general math.
Recovery
- Undo and resample the black point, or reduce the stretch factor if color saturates unevenly.
Statistical Stretch 1.18.0 source-inspected
- Run Statistical Stretch on the linear image with Linked channels enabled.
- Choose a preset by target: default for an ordinary galaxy/broadband target, brighter for a dim target or very dark sky, globular for a dense star cluster.
- This is the same underlying algorithm Siril's licensed Seti Astro integration exposes -- both trace to the same statistical-stretch design, hosted differently.
Controls and starting ranges
- stat_default
- target_median 0.08, linked, blackpoint_sigma 4.0, curves_boost 0.05 -- sky should land ~0.06-0.08
- stat_bright
- target_median 0.13, linked, blackpoint_sigma 4.0, curves_boost 0.05 -- dim targets or very dark skies
- stat_globular
- target_median 0.11, linked, blackpoint_sigma 5.0, curves_boost 0.05 -- Jeff-confirmed good on C 80 (8.2/10 vs a pipeline stf_nebula run's 6.2/10); lowered from 0.15 after a globular over-stretched with core clipping
Mask behavior: Not applicable; full-image linked stretch.
Failure modes
- Using the galaxy/broadband preset on a dense globular, which needs the extra shadow headroom the globular preset provides.
Recovery
- Revert to the linear input and choose the preset matching the actual target density.
GHS Stretch 1.18.0 source-inspected
- Run GHS Stretch on the linear image with the pivot set near the sky background, not a generic 0.25.
- In this pipeline's automatic parameter selection, only alpha (stretch strength) and pivot are data-driven from the image's dynamic range; beta, gamma, lp, and hp stay at their function defaults regardless of target -- do not assume every GHS control is being tuned per-image.
- Choose the galaxy preset for a stronger core-to-arm range; the default preset otherwise.
Controls and starting ranges
- ghs_default
- alpha 5.0, beta 0.0, gamma 3.0, pivot 0.02, channel K
- ghs_galaxy
- alpha 8.0, beta -0.2, gamma 4.0, pivot 0.02, channel K -- stronger core-to-arm range
- pipeline auto-selection
- alpha and pivot only; beta/gamma/lp/hp are not varied by this pipeline's own parameter logic
Mask behavior: Not applicable; full-image operation.
Failure modes
- Setting the pivot well above the sky background, which is a documented way to lift real signal into false brightness rather than stretch from the true floor.
Recovery
- Revert and re-anchor the pivot to a measured background level.
Validation status
Not yet Jeff-validated. Use this as sourced guidance, not a certification.
Sources
- M66 manual recipe verification feedback
M66_Manual_Recipe_Verification_Feedback.md— Jeff validated - NOVA stretch engines: stat_stretch/ghs_stretch (real SASpro calls), stf_stretch/veralux_stretch/smart_stretch (NOVA-original, no external tool), PixInsight MultiscaleAdaptiveStretch, and ontology variants
nas_server/seti_astro.py:273 (stf_stretch, pure NumPy, no setiastro import), nas_server/seti_astro.py:376 (stat_stretch, calls setiastro.saspro.imageops.stretch), nas_server/seti_astro.py:421 (ghs_stretch, calls setiastro.saspro.ghs_preset), nas_server/seti_astro.py:1136 (veralux_stretch, pure NumPy, NOVA-original, no setiastro import), nas_server/seti_astro.py:1319 (smart_stretch, adaptive orchestration over the above); nas_server/pixinsight.py:223 (mas flag); nas_server/pi_postprocess.js:813-833 (MultiscaleAdaptiveStretch PJSR call, no parameter override in M66's run); nas_server/tool_params.py:250-274 (compute_ghs: only alpha and pivot are data-driven, beta/gamma/lp/hp stay at function defaults); nas_server/processing_ontology.json:956 (13 experiment_variants across 6 engines)— NOVA source-confirmed - M66 workflow 1.24.7 execution record
critiques/20260802_045251_seestar_galaxy.json— NOVA execution record - Project-authored Siril native-stretch guidance (SIRIL_MANUAL['stretch'])
nas_server/recipe_page.py:116— Reasoned translation - Jeff: Siril has a separately installed Veralux Python script (2026-08-15)
Jeff, direct confirmation, 2026-08-15 conversation— Jeff validated - Installed Seti Astro Suite Pro 1.18.0 processing source
saspro/pedestal.py; saspro/numba_utils.py; saspro/stacking_suite.py; saspro/abe.py; saspro/sssc.py— Artifact-confirmed
Related evidence
The M66 recipe and Jeff-validation ledger will link here when their static exports are available. Until then, this article remains explicitly unvalidated.

