Skip to main content

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 xlam via 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_bias fits 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_A are set, in which case the sharper of the two is automatically convolved down to match the coarser one before fitting (see kinextract.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_red and 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). Use assess_recovery_bias to 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

kinextract-0.2.0.tar.gz (213.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kinextract-0.2.0-py3-none-any.whl (203.6 kB view details)

Uploaded Python 3

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

Hashes for kinextract-0.2.0.tar.gz
Algorithm Hash digest
SHA256 67d2d9c62111f76eb133d86cab816707f1cda07b312bb63daf0265bf72f188c8
MD5 2d0835bd959e17ff99ed294aa6751558
BLAKE2b-256 138e56340236e98aa57429647a7206dd649dea4850d7d8248bb21f5ceed12405

See more details on using hashes here.

Provenance

The following attestation bundles were made for kinextract-0.2.0.tar.gz:

Publisher: publish.yml on thomas-k-waters/kinextract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for kinextract-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d79710fc165d3f174205414457545438834996e668fcc8ee2027f2c8319cc6ec
MD5 8e6cc822a9aea3a00f47079338129540
BLAKE2b-256 ca0c213d866434f94764568f5a0b63c2c5b82704a142c30ec2ccf60ac439082b

See more details on using hashes here.

Provenance

The following attestation bundles were made for kinextract-0.2.0-py3-none-any.whl:

Publisher: publish.yml on thomas-k-waters/kinextract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page