(Image + Combiner + Rust(rs)), made for Python.
imcombiners was built for astronomical image-stack combination. Generic reductions now live in the companion reducers package; imcombiners focuses on stack combination plus imcombine-style rejection. Pure stack reductions use reducers with imcombiners' finite-only policy: both NaN and inf are skipped.
Documentation: https://ysbach.github.io/imcombiners/ GitHub: https://github.com/ysBach/imcombiners
The package started as a tool for the main developer(@ysBach)'s reduction tools (ysfitsutilpy). It is a result of their graduate school life, TA experience (2016-2023), and astropy image combination TF experience (2020). After years of use & trial using numba, I finally rewrote the core in Rust for better speed, reliability, and maintainability.
Now it targets a modern Python API around Rust kernels, with IRAF IMCOMBINE compatibility but with better speed & API.
Tests and benchmark material compare supported paths against IRAF, Astropy/NumPy, ccdproc, and bottleneck where appropriate. On a personal laptop (Apple M4 Pro), I experience a factor of few speedup over IRAF and dozens times over Python-based tools (astropy/ccdproc/bottleneck) for typical use cases. See the Documentation.
The package has four usage modes:
- Recommended: Standard
Combiner().combine()approach, - CLI-friendly: compact
ndcombine()wrapper, - Deep-inspection: Chained
Combiner(), and - Advanced: direct kernel calls.
Start with standard Combiner usage for ordinary Python workflows.
import numpy as np
import imcombiners as imc
rng = np.random.default_rng(20250311)
stack = rng.normal(1000, 5, (15, 256, 256)).astype("float32")
cmb = imc.Combiner(stack)
out = cmb.combine(
"median", # final stack-combination method
# 1. Optional pre-rejection threshold masking
thresholds=(0.0, 65000.0),
# 2. Optional per-image zero/scale normalization
zero=None,
scale="median",
# 3. Optional pixel rejection before final combination
rejectors=[
imc.MinMaxClip(n_min=1, n_max=0.1),
imc.SigClip(sigma=3.0, maxiters=5),
],
diagnostics=None, # output-only fast path
)See docs/quarto/index.qmd for the detailed explanations, API-level guidance, and conventions behind this example.
- Stack combination: mean, median, lower median, percentiles, sum, min, max, variance, and weighted mean via
weight=. - 1-D rejection helpers:
imcombiners.kernelsexposes_1dfunctions such assigclip_mask_1d,pclip_1d, andminmax_combine_1d. Use the companionreducerspackage for standalone fast reductions such as mean, median, percentile, and variance. - Pixel rejection: sigma, CCD noise-model, iterative linear, min/max, and IRAF-style percentile clipping. Rejection centers accept mean, median, and lower median (
lmedian/lmed). - Pipeline helpers: threshold masking, zero/scale normalization, offset padding, masks,
diagnostics=None|"simple"|"full", and output-only fast paths. - See documentations for details and examples.
For Python projects:
uv add imcombinersOR
uv pip install .OR
uv pip install -e .For Rust crate use:
[dependencies]
imcombiners = "0.1.1"uv run pytest
uv run --extra bench python benchmarks/benchmark_combine.py
uv run python benchmarks/benchmark_threads.py--quick runs the smoke benchmark matrix. Omit it to run the full table that
backs the published benchmark documentation.
