Non-parametric binned-LOSVD spectral fitter for galaxy kinematics
Project description
kinextract
NOTE: This package is actively being developed. Please let me know if you encounter any issues or if you have suggestions for improvement. You can reach me via email at thomas.k.waters@gmail.com.
Non-parametric binned-LOSVD spectral fitter for galaxy kinematics
kinextract fits galaxy spectra using a non-parametric line-of-sight velocity distribution (LOSVD) represented directly on a velocity grid — no Gauss-Hermite parametrisation assumed. An asymmetric-least-squares (ALS) baseline is co-fitted with the LOSVD, and regularization strength is selected automatically via a roughness criterion. The package targets integral-field-spectroscopy data (MUSE, STIS) for black-hole mass measurements through Schwarzschild orbit modelling.
Features
- Non-parametric LOSVD: recovers arbitrary shapes including double-peaked and asymmetric distributions
- Automatic regularization: grid-searches
xlamvia a chi-squared or roughness + unimodality criterion - Continuum co-fitting: asymmetric least-squares (ALS) baseline by default, or a low-order asymmetric-reweighted polynomial (
FitConfig.continuum_method = "polynomial") as a less over-smoothing-prone alternative - JAX acceleration: analytic JIT-compiled gradients, installed by default, for a large speedup and more reliable convergence over plain finite differences
- Instrumental LSF matching: optionally convolves the sharper of the data/templates down to match the coarser one before fitting, given both resolutions (see
FitConfig.data_fwhm_A/template_fwhm_A) - Uncertainty estimation: Laplace approximation (with active-set conditioning and a convergence diagnostic), residual bootstrap, and bias correction (via
LOSVDErrorEstimator) - Empirical recovery-bias validation:
assess_recovery_biasfits matched mock spectra (same instrument, templates, continuum, and noise level as a real target) on a grid of known truths, so bias near the instrumental resolution limit can be measured directly rather than assumed - Self-documenting configuration:
FitConfig.describe()prints every tunable field, grouped by subsystem, optionally filtered by a substring (e.g.FitConfig.describe("als"))
Installation
pip install kinextract
This installs everything needed for the primary MAP + bootstrap pipeline,
including JAX and Numba for fast fitting. The optional full-posterior
(NUTS/HMC) path in kinextract.bayesian needs NumPyro on top:
pip install "kinextract[bayesian]"
pip install kinextract works the same way inside a conda environment;
there is no separate conda package.
From source:
git clone https://github.com/thomas-k-waters/kinextract
cd kinextract
pip install -e ".[dev]"
Requires Python ≥ 3.10.
Documentation
Documentation for kinextract is available at Read the Docs.
Quick start
from kinextract import run_spectral_fit, load_config_from_toml
cfg = load_config_from_toml("kinextract.config")
fit = run_spectral_fit(cfg, gal_file="bin0105.spec")
# Inspect the fit
v = fit["state"].xl # velocity grid (km/s)
b = fit["outputs"]["b"] # recovered LOSVD
chi2_red = fit["outputs"]["chi2_red"]
print(f"chi2_red = {chi2_red:.3f}")
# Plot
from kinextract import plot_fit, plot_als_continuum
plot_fit(fit)
plot_als_continuum(fit) # only if cfg.fit_als_continuum = True
See FitConfig.describe() (or help(FitConfig)) for every tunable field,
grouped by subsystem, e.g. FitConfig.describe("xlam") for just the
regularization-selection options.
Configuration
Copy examples/kinextract.config to your extraction directory
and edit the galaxy-specific parameters:
[wavelength]
zgal = 0.00157811 # galaxy redshift
wavefitmin = 8400.0 # fit range (Å)
wavefitmax = 8800.0
[kinematics]
xlam_auto = true # auto-select regularization
xlam_smooth_threshold = 0.25
[continuum]
fit_als_continuum = true
TOML section names are purely organizational — every field is flattened into a single
FitConfig namespace regardless of which section it's under. examples/kinextract.config
documents the most commonly-tuned fields inline; for the complete list, call
FitConfig.describe() (see Quick start above) or read the FitConfig class docstring.
Error estimation
from kinextract import LOSVDErrorEstimator, load_config_from_toml, run_spectral_fit
cfg = load_config_from_toml("kinextract.config")
fit = run_spectral_fit(cfg, gal_file="bin0105.spec")
est = LOSVDErrorEstimator(fit, cfg)
laplace = est.laplace_covariance()
boot = est.residual_bootstrap(n_bootstrap=200, n_jobs=4)
summary = est.summarize(laplace_result=laplace, bootstrap_result=boot)
est.plot_losvd_with_errors(summary)
Running tests
pip install -e ".[dev]"
pytest # fast tests only (~2 s)
pytest -m slow # include slow integration tests
Package structure
src/kinextract/
config.py FitConfig dataclass + TOML loader
state.py FitState dataclass (holds spectrum, templates, LOSVD)
continuum.py ALS continuum fitting (standalone math + fit-time)
numerics.py Objective function, JAX kernel, chi-squared, convolution
masking.py Emission-line masking, sigma-clipping, cleaning
losvd.py LOSVD analysis: roughness, peak counting, GH fitting
spectrum.py Spectrum loading, wavelength rebinning, FitState construction
fitting.py MAP fitting loop, automatic xlam selection, top-level API
io.py File I/O (spectra, templates, output .fit/.ascii/.rms files)
templates.py Template reading/interpolation, instrumental LSF matching
plotting.py Diagnostic plots (fit residuals, LOSVD, ALS continuum)
errors.py LOSVDErrorEstimator (Laplace + bootstrap + bias correction)
mocks.py Matched mock-spectrum generation for recovery-bias validation
validation.py assess_recovery_bias / correct_recovered_losvd
bayesian.py Optional full-posterior (NUTS/HMC) alternative to the MAP pipeline
Known limitations
- Input spectra and templates must share the same logarithmic wavelength grid.
- Instrumental resolution (LSF) is assumed matched between the data and the templates unless
FitConfig.data_fwhm_A/template_fwhm_Aare set, in which case the sharper of the two is automatically convolved down to match the coarser one before fitting (seekinextract.templates.resolution_mismatch_sigma_A). Both fields must be supplied together (there is no built-in database of instrument/library LSF values — you must supply your own, e.g. from the instrument handbook and the template library's documentation). - LOSVD recovery is sensitive to the velocity grid and regularization choice; inspect diagnostic plots.
- At low S/N, fine-scale LOSVD structure is not reliable — check
chi2_redand the roughness value. - Template mismatch can bias the LOSVD; run with multiple template libraries and compare.
- Emission lines are masked but not modelled; simultaneous emission fitting is not supported.
- Near the instrumental resolution limit, recovered V/sigma carry a real, condition-dependent bias
(see
FitConfig's "Known limitations" section for details and typical magnitudes). Useassess_recovery_biasto measure this directly for a specific target's instrument/S-N/template configuration, rather than relying on generic numbers.
Citation
If you use kinextract in published research, please cite:
@software{kinextract,
author = {Waters, Thomas K.},
title = {kinextract: Non-parametric binned-LOSVD spectral fitter for galaxy kinematics},
year = {2026},
url = {https://github.com/thomas-k-waters/kinextract},
}
See also CITATION.cff for the full citation metadata.
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kinextract-0.2.0.tar.gz.
File metadata
- Download URL: kinextract-0.2.0.tar.gz
- Upload date:
- Size: 213.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67d2d9c62111f76eb133d86cab816707f1cda07b312bb63daf0265bf72f188c8
|
|
| MD5 |
2d0835bd959e17ff99ed294aa6751558
|
|
| BLAKE2b-256 |
138e56340236e98aa57429647a7206dd649dea4850d7d8248bb21f5ceed12405
|
Provenance
The following attestation bundles were made for kinextract-0.2.0.tar.gz:
Publisher:
publish.yml on thomas-k-waters/kinextract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kinextract-0.2.0.tar.gz -
Subject digest:
67d2d9c62111f76eb133d86cab816707f1cda07b312bb63daf0265bf72f188c8 - Sigstore transparency entry: 2120718145
- Sigstore integration time:
-
Permalink:
thomas-k-waters/kinextract@9402236be21091e638dd6ff1c9ecfe8f7abb8704 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/thomas-k-waters
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9402236be21091e638dd6ff1c9ecfe8f7abb8704 -
Trigger Event:
release
-
Statement type:
File details
Details for the file kinextract-0.2.0-py3-none-any.whl.
File metadata
- Download URL: kinextract-0.2.0-py3-none-any.whl
- Upload date:
- Size: 203.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d79710fc165d3f174205414457545438834996e668fcc8ee2027f2c8319cc6ec
|
|
| MD5 |
8e6cc822a9aea3a00f47079338129540
|
|
| BLAKE2b-256 |
ca0c213d866434f94764568f5a0b63c2c5b82704a142c30ec2ccf60ac439082b
|
Provenance
The following attestation bundles were made for kinextract-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on thomas-k-waters/kinextract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kinextract-0.2.0-py3-none-any.whl -
Subject digest:
d79710fc165d3f174205414457545438834996e668fcc8ee2027f2c8319cc6ec - Sigstore transparency entry: 2120718280
- Sigstore integration time:
-
Permalink:
thomas-k-waters/kinextract@9402236be21091e638dd6ff1c9ecfe8f7abb8704 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/thomas-k-waters
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9402236be21091e638dd6ff1c9ecfe8f7abb8704 -
Trigger Event:
release
-
Statement type: