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.4.tar.gz (23.1 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.4-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: zestimatr-0.1.4.tar.gz
  • Upload date:
  • Size: 23.1 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.4.tar.gz
Algorithm Hash digest
SHA256 6e10d258e6fca13ed6ad2697ef3f9432853ed05d4c19263de0469f7bb7e06c49
MD5 0db0a2ed637c98c917faf7436f07ad83
BLAKE2b-256 e7011d2078b11eb6c82a9019067a8373e6bb98f47553e796c9fd1698ac01b00e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: zestimatr-0.1.4-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.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ba4cecc7c8987d64656b5d2536b516f2ecf302d2837ebcdac75806eb8d5bc3f8
MD5 bdef5adbd93bfaadb7244242995d624d
BLAKE2b-256 b657acb745c78faca44291a6ed7748d4ae30fe6be0a5664e7fff844758bb7757

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