Skip to main content

Spectroscopic redshift estimation with uncertainty quantification

Project description

zestimatr

PyPI Python License: MIT Documentation Hugging Face DOI arXiv A rectangular badge, half black half purple containing the text made at Code Astro

Spectroscopic redshift estimation from high-resolution galaxy spectra, with uncertainty quantification.

zestimatr is a Python package that uses a residual 1D convolutional neural network with an MLP head to predict redshifts directly from high-resolution spectral flux. The model outputs both a point estimate and a calibrated uncertainty (predicted standard deviation) for each spectrum.

Installation

pip install zestimatr

Or install from source:

git clone https://github.com/aryana-haghjoo/zestimatr.git
cd zestimatr
pip install -e .

Quick Start

You can run the following command below to predict the redshift for a given spectrum npz file.

python run_zestimatr.py $PATH_to_data_file

The code below can also be pasted into a notebook or .py file to predict the redshift for a spectrum. Just pass your flux array (and optionally the corresponding wavelength array) — normalization and resampling are handled automatically.

import numpy as np
import zestimatr

# Load a spectrum
data = np.load("galaxy300_spectrum.npz")
flux = data["flux_high"]
wavelength = data["wavelength_high"]

# Download and load pretrained model from Hugging Face
checkpoint_path = zestimatr.download_pretrained()
zhead, norm_params = zestimatr.load_model(checkpoint_path)

# Predict — pass wavelength to automatically resample to the training grid
result = zestimatr.predict(flux, zhead, norm_params, wavelength=wavelength)

print(f"Predicted: z = {result['z_pred']:.4f} +/- {result['z_uncertainty']:.4f}")

If your spectrum is already on the training wavelength grid (2500 points, 1–5 μm), you can omit the wavelength argument. For batch prediction, pass a 2-D flux array of shape (N, L):

# Batch prediction
flux_batch = data["flux_high"]  # shape (N, L)
results = zestimatr.predict(flux_batch, zhead, norm_params, wavelength=wavelength)
print(results["z_pred"])  # shape (N,)

Emission Line Detection

After estimating a redshift, you can detect and visualize emission lines in the spectrum:

# Detect lines — returns a pandas DataFrame
lines = zestimatr.detect_emission_lines(wavelength, flux, result["z_pred"])
print(lines)

# Plot spectrum with emission lines marked as dashed vertical lines
zestimatr.plot_spectrum(wavelength, flux, z=result["z_pred"])

The built-in catalog includes 16 common rest-frame lines (Ly-alpha, H-alpha, H-beta, [O II], [O III], [N II], [S II], and more). Detection uses a local peak-finding approach with a configurable sigma_thresh (default 3.0).

Metrics

zestimatr provides two evaluation functions:

  • compute_metrics(z_pred, z_true) -- accuracy metrics:

    • MAE, RMSE, NMAD
    • Median |dz|/(1+z)
    • Outlier rate (fraction with |dz|/(1+z) > 0.15)
  • compute_calibration_metrics(z_pred, z_true, z_uncertainty) -- uncertainty calibration:

    • Calibration std and mean of normalized residuals
    • 1/2/3-sigma coverage fractions
    • Median predicted uncertainty

For Developers

Most users only need the base install above. The following is for retraining or rebuilding the dataset from raw JADES data.

Extra dependencies

# Training only
pip install -e ".[train]"

# Data preprocessing only (astropy, scipy)
pip install -e ".[preprocess]"

# Everything
pip install -e ".[train,preprocess]"

Data preprocessing

Prepare train/eval datasets from JADES DR4 FITS files. The pipeline splits at the object level before augmentation to prevent data leakage:

python scripts/prepare_dataset.py --jades_dir /path/to/JADES_data/DR4

This produces data/train_DR4.npz (augmented training set) and data/eval_DR4.npz (held-out evaluation set).

Training

python scripts/train.py --train_data data/train_DR4.npz --eval_data data/eval_DR4.npz --wandb_mode online

Key training options:

Flag Default Description
--hidden_dim 128 Conv block hidden dimension
--num_blocks 6 Number of residual conv blocks
--dropout 0.2 Dropout rate
--epochs 200 Training epochs
--lr 3e-4 Learning rate
--batch_size 32 Batch size
--wandb_mode online online, offline, or disabled

Training logs and plots are synced to Weights & Biases.

Pretrained Model

A pretrained checkpoint trained on JADES DR4 (52,647 spectra) is available on Hugging Face.

Download it automatically:

import zestimatr

path = zestimatr.download_pretrained()
zhead, norm_params = zestimatr.load_model(path)
Metric Value
MAE 0.141
RMSE 0.323
Median|dz|/(1+z) 0.012
Outlier rate 5.7%
Calibration std 0.84

Data Format

Input .npz files should contain:

  • flux_high -- high-resolution spectral flux, shape (N, L) for datasets or (L,) for a single spectrum
  • z -- ground truth redshifts, shape (N,) or scalar (also accepts keys: redshift, z_true, z_spec)
  • wavelength_high -- wavelength array, shape (L,). If provided (along with wavelength to predict()), spectra are automatically resampled onto the model's training grid (2500 points, 1–5 μm). If omitted, flux is assumed to already be on the training grid.

Optional keys: flux_high_err, id, ra, dec.

Project Structure

zestimatr/
├── src/zestimatr/          # Package source
│   ├── model.py             # ZHead1D network + loss function
│   ├── dataset.py           # PyTorch dataset for training
│   ├── metrics.py           # Accuracy and calibration metrics
│   ├── inference.py         # Model loading + prediction pipeline
│   ├── plotting.py          # Validation plots
│   └── emission_lines.py    # Emission line detection + spectrum plotting
├── scripts/
│   ├── prepare_dataset.py   # Data extraction, quality cuts, split, augmentation
│   └── train.py             # Training CLI (not part of the package)
│   └── run_zestimatr.py.    # Predict redshift for a given spectrum
├── tests/
│   └── test_metrics.py      # Unit tests
├── tutorials/
│   ├── quickstart_single_spectrum.ipynb  # Single spectrum tutorial
│   ├── quickstart_batch_spectra.ipynb    # Batch (200 spectra) tutorial
│   ├── galaxy300_spectrum.npz            # Example single spectrum
│   └── sample_200_spectra.npz            # Example 200-spectrum sample
├── pyproject.toml           # Package metadata
└── README.md

License

MIT

Authors

Code/Astro 2026 Group 2:

  • Aryana Haghjoo ORCID
  • Lau, Marie Wingyee ORCID
  • Michele Woodland

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

zestimatr-0.1.3.tar.gz (23.0 kB view details)

Uploaded Source

Built Distribution

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

zestimatr-0.1.3-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

Details for the file zestimatr-0.1.3.tar.gz.

File metadata

  • Download URL: zestimatr-0.1.3.tar.gz
  • Upload date:
  • Size: 23.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for zestimatr-0.1.3.tar.gz
Algorithm Hash digest
SHA256 d1d82042113bb98c847089bf2b51fdfe196060b4801e6182e76d5016124d7654
MD5 b62fa3f07e3a91c3eb827eea962c9f20
BLAKE2b-256 e727a4a46ff75b51814fef891e5c4599144b93c29f9944104272a34c35b083bd

See more details on using hashes here.

File details

Details for the file zestimatr-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: zestimatr-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 16.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for zestimatr-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 3c489397993bf68e6fa65cf1964390d567ef9eef85f6e921c786a48aa5bda407
MD5 848612055c3fb91dd3faeb2d21d159b6
BLAKE2b-256 f17a99d528308b09b8cd0a51f3fe88549b96e6f1f67b34dbbe1be917ca09dd4a

See more details on using hashes here.

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