Svenesis ImageMono Train
Version 1.7.12 – GPL-3.0-or-later
🚧 Current version 1.7.12. Not yet in the official Siril Script Repository – download directly from GitHub.
ImageMono Train processes an entire night of mono camera and filter wheel data in a single run: it reads every FITS header, groups the lights by filter, calibrates and stacks each channel separately, aligns the finished masters pixel for pixel, and composes them into a colour-calibrated image – without a single Siril command typed by hand.
📖 The story behind it, and what I learned about mono processing along the way: Seven Filters, One Button →
Who is this for?
For mono rigs with a filter wheel – cameras without a Bayer matrix, where colour comes from separately captured filter channels. Frames are never debayered; the entire pipeline is monochrome. It is therefore deliberately not suited to one-shot-colour cameras.
Supported palettes
- LRGB – natural colour with separate luminance
- RGB – red, green, blue without luminance
- HaRGB – standard RGB with Ha blended into the red
- Narrowband assignments – SHO (Hubble), HOO, HSO, HOS, OSS, OHH, OSH, OHS and HSS
- Realistic1 and Realistic2 – weighted mixes rather than plain assignments
The Auto setting proposes a palette whose three channels can actually be filled; two filters are enough for HOO, because OIII feeds both green and blue. The channel mapping stays editable.
Deliberately absent are the dynamic palettes of the Foraxx family: their t^(1−t) factor collapses at linear brightness, and the script hands the image over linear on purpose.
Two steps that were taken back out
Both for the same reason: the composite is deliberately handed over linear, and neither step was.
SCNR no longer runs on the composite. Siril computes green removal as green = min(green, (red + blue) / 2). On a broadband image that is the right cure for colour noise – but in a mapped palette the green channel carries a real emission line, Hα in SHO, and the expression clips measured flux wherever it dominates: on an M 16 run about 3 per cent of the Hα on average, considerably more in the bright pillars. Green removal is now listed in todo.md as your own step after stretching.
The Hα blend in HaRGB has become linear. It used to be a screen blend, 1−(1−R)·(1−k·Ha), whose cross term is quadratic in flux. Invisible at the faint end, but at R = 0.8 and k·Ha = 0.4 it yields 0.88 instead of 1.2 – 27 per cent of compression on exactly the stars and nebula cores you go on to stretch. It is now (R + k·Ha) / (1+k), a weighted sum, and the log names the two weights used.
Rejection based on usable frames
The rejection algorithm is chosen per filter – based on the frames that are actually integrated, not the ones that were captured. A channel that lost half its frames to clouds is treated accordingly:
- ≤ 4 frames – percentile clipping (sigma methods need a population)
- 5–10 frames – sigma clipping
- 11–30 frames – Winsorized sigma, the workhorse for a normal night
- 31–300 frames – GESDT
- above 300 frames – linear fit 5/4, which models a trend across the stack
The band edges come from Cyril Richard's AMSP script in the official Siril repository. A Siril build that doesn't know GESDT falls back to linear fit and records that in the report.
Calibration
All of it optional and additive: session flats per filter, darks and bias from a reusable library folder. Matching runs on the FITS headers rather than filenames: camera, gain, binning and image dimensions must match exactly, temperature within ±2 °C. The exposure time, however, is a 5 percent band – the thermal signal grows with time, so a 290-second dark removes very nearly what a 300-second one would, and refusing it would leave the lights uncalibrated. Which dark was used is named in the log; beyond the band the run continues without one and says so.
Further safeguards: darks are additionally grouped by temperature, so −10 °C and −20 °C can never be averaged into a master that is correct for neither. Bias is never applied together with a dark, because the master dark already contains the offset. And a filter mixing several exposure times is calibrated in parts – each exposure with its own dark. Cosmetic correction removes hot and cold pixels on request. Finished masters land in calib/ under readable names and are reused on later runs.
Cross-filter alignment
Hours pass between the Ha stack and the OIII stack, and in that time the field has drifted and rotated slightly. That's why all masters are registered together once more and projected onto their common overlap using -framing=min – only then do they share a pixel grid and the composite stays free of colour fringes.
How much this depends on the selection shows in a measurement from one M 16 night: with all six masters aligned together, Siril's two-pass registration picks its own reference – and a star-rich broadband channel wins. OIII then found only 12 star pairs and the SPCC fit landed at sigma 5.76. Restrict the pool to Ha and OIII, and it's 1,165 pairs at sigma 2.73. That is precisely why stacking can be limited to the filters a palette reads.
Spectrophotometric colour calibration
Instead of generic PCC, the script uses SPCC with your sensor's quantum efficiency and the actual filter passbands. For narrowband it computes from the emission lines – Ha 656.3 nm, OIII 500.7 nm, SII 671.6 nm – along with the bandwidth you entered. The sensor name is verified before the run against the very SPCC database Siril itself uses (read-only). That check matters because an unknown name is not an error to Siril – it quietly substitutes something else. The IMX533, for instance, appears in the tables only as the OSC variant, while the mono chip is listed under Sony IMX411/455/461/533/571; a filter-wheel rig would otherwise be calibrated as a colour camera without anyone noticing. Missing, ambiguous or partially matching names are reported – and a database that cannot be located means cannot check, never invalid.
Reports that gloss over nothing
Every run writes two Markdown files into the output folder. output.md records what actually happened – which channel got which algorithm, which calibration applied, what was skipped and why. todo.md describes the hand-work that follows, with the specific menu paths in Siril. Both describe the real run rather than the normal case: skipped filters, fallbacks and discarded frames are named explicitly.
View sample report View sample guide
Reusing masters
The aligned masters stay in the masters/ folder. That lets you recompose a different palette in seconds without stacking again. If the masters sit on different grids – after a run that only built the filters of one palette, for example – the script refuses to mix them rather than producing a broken image.
Further features
- Multiple nights are pooled automatically when they sit under one target folder
- Supports
.fit,.fits,.ftsand Rice-compressed.fzvariants - Quality filters by FWHM, roundness, star count and background – deliberately active only from 20 frames upwards
- Weighting by sharpness, noise or star count
- Optional rejection maps for quality control
- Background extraction as a polynomial or an RBF model, which can follow a gradient that changes direction across the frame
- Optional synthetic luminance for narrowband nights – an unweighted mean, and the run says so: a markedly weaker channel drags the result down, so hold it against your strongest channel before going on
- The report carries measured values: after registration the script reads Siril's sequence data back – FWHM, roundness and star count per channel. Anything Siril didn't record shows as "—", never as a zero
- Flats pooled from several nights are checked against each other before being combined – on averaged, block-binned maps rather than single frames, and against a noise floor it measures itself: the reference night is halved and compared with itself, because two halves of the same night differ by nothing but noise. Below that, the run reports “no shape difference detectable” instead of a number without meaning
- Disk usage stays bounded, because each generation of intermediates is freed as soon as the next one is complete
- Output stays linear – with a stretched preview on request
Requirements
Siril 1.4+ with Python support, sirilpy, PyQt6, astropy, numpy – dependencies are installed automatically on first launch. Colour calibration needs an internet connection or a local Gaia catalogue; without either, the composite is still produced, just uncalibrated.
⚠️ Don't work inside cloud folders. Siril links the frames via symlinks. Dropbox, OneDrive, iCloud Drive and Google Drive rewrite those mid-run, which can make files vanish between two commands. Either work on a local disk, or at least exclude output/_work/ from syncing.