Skip to main content

specsr

Physics-informed deep learning for super-resolving galaxy spectra

arXiv DOI Hugging Face PyPI CI Docs Python License: MIT


specsr sharpens low-resolution galaxy spectra by roughly a factor of ten in resolving power (R ~ 100 → R ~ 1000), recovering narrow emission-line structure — including blended doublets such as [O III] λλ4959,5007 and Hβ — that is unresolvable at prism resolution. It is trained on paired JWST/NIRSpec observations from JADES, where each galaxy contributes a prism spectrum and a stitched medium-resolution grating reference.

from specsr.inference import SpecSRPipeline

pipeline = SpecSRPipeline.from_pretrained()      # weights fetched from the Hub
result = pipeline(flux_low, wavelength_low)      # your own wavelength grid

result.sr1           # super-resolved spectrum
result.sr2           # after physics-informed line refinement
result.sr2_sigma     # wavelength-dependent predictive uncertainty
result.z             # inferred redshift, with result.z_sigma
result.wavelength    # the model's grid, in microns

Pass wavelength_low unless your spectrum is already on pipeline.wavelength: the input is then resampled onto the model's grid by integration rather than interpolation, so line flux is preserved. SpecSRPipeline.from_checkpoints(dir) loads a local set of weights instead of the Hub.

Installation

pip install "specsr[hub]"

PyTorch is required. On a GPU machine, install the build matching your driver from the official index before installing specsr, so pip does not resolve a mismatched CUDA stack. Extras: [hub] for automatic weight download, [train] for the training stack, [all] for everything. To track main instead of a release: pip install "git+https://github.com/aryana-haghjoo/specsr.git#egg=specsr[hub]".

Tutorials

Three executable notebooks in tutorials_for_user/, with real held-out JADES spectra bundled so they run with no survey data and no configuration:

notebook covers
01_quickstart.ipynb run the chain on one spectrum, read the output, plot it fairly
02_your_own_spectrum.ipynb arbitrary wavelength grids, resampling, and what grid coarseness does to lines
03_batches_and_trust.ipynb batches, uncertainty calibration, flux recovery vs line brightness, failure modes

How it works

Three-stage spectral super-resolution pipeline

Three stages, trained in sequence, each freezing the one before it:

stage role parameters
SR1 1D residual CNN backbone: prism → grating-like reconstruction, with a per-pixel variance 1,391,042
ZHead redshift inference from SR1's output; a softmax PDF over 1,024 bins spanning 0 ≤ z ≤ 15 710,145
SR2 residual refiner: attention over 98 emission-line tokens, each a parametric Gaussian gated by a supervised presence probability, plus a CNN continuum branch 1,000,518

Every number on the diagram is read off the released checkpoints at draw time by scripts/make_architecture_figure.py, and its inset panels are real predictions for a held-out galaxy — a retrain that changes a width or a depth changes the figure rather than silently invalidating it. ARCHITECTURE.md explains the design and the invariants the code enforces.

What it does and does not do

Deblends features unresolved at prism resolution, improves emission-line S/N for [O II], Hβ, [O III] and Hα, reaches noise-limited residuals above ~2 µm, and recovers redshift information approaching that of the high-resolution reference. It applies a learned prior from the training distribution: it cannot reconstruct features that have no statistical relationship with the prism data.

Limitations, all measured rather than suspected:

  • Absolute flux scale is not predicted — only spectral shape.
  • Line-flux recovery is a strong function of line brightness. Bright lines keep most of their flux; faint ones are systematically under-recovered. Any flux-accuracy figure quoted without a signal-to-noise cut attached is meaningless.
  • Super-resolution does not improve line fluxes over the input. Measured with profile fits, the prism already recovers the total flux of strong lines (median ratio to the reference 0.91–1.09, 2–11% of lines off by more than a factor of two); the reconstruction is lower and more scattered (0.72–0.87, 24–30%). Take total line fluxes from the input spectrum.
  • The redshift head is a conditioning stage, not a redshift pipeline. Its catastrophic-outlier rate is high enough that a redshift should be checked against the line positions it implies.
  • Super-resolution does not beat direct fitting of the prism on the [O III] doublet-ratio test.
  • The paired training sample is small by machine-learning standards, and generalisation to populations underrepresented in JADES — very dusty systems, low-mass galaxies, the highest-redshift sources — is not established.
  • Performance degrades below ~1.5 µm, where both the input and the reference have low S/N.

The model card carries the full performance tables, with scatter and sample sizes.

Command line

specsr build-dataset --release DR4      # raw JADES x1d products -> paired dataset

specsr train sr1   --config configs/sr1.yaml --out-dir runs/sr1
specsr train zhead --config configs/zhead.yaml --source sr1 --out-dir runs/zhead \
    --sr1-ckpt runs/sr1/best_superres_model.pth --sr1-config configs/sr1.yaml
specsr train sr2   --config configs/sr2.yaml --out-dir runs/sr2 \
    --sr1-ckpt runs/sr1/best_superres_model.pth --sr1-config configs/sr1.yaml \
    --zhead-ckpt runs/zhead/best_zhead.pth

specsr infer --dataset data/paired_DR4_logR.npz --idx 0 10 42 --save predictions.npz
specsr evaluate line-flux

Upstream checkpoints are named explicitly rather than discovered, so every model records what it was trained on top of. Everything the package writes — figures, predictions, evaluation tables — goes under SPECSR_OUTPUT_DIR (default ./outputs). See the training guide.

Data

Raw JWST/JADES data is not distributed with the package. You need it only to rebuild the dataset or retrain — running the released models on your own spectra requires nothing but the weights, which download on first use.

export SPECSR_JADES_ROOT=/path/to/JADES_data   # contains DR3/, DR4/, ...
export SPECSR_DATA_DIR=/path/to/derived        # where built products are written
specsr build-dataset --release DR4

The data guide covers where to download each release and the directory layout the builder expects.

Splits are drawn over parent galaxies, never over rows. Each galaxy contributes 21 highly correlated rows — one real spectrum plus 20 augmented realisations — and only training galaxies are augmented, so a held-out galaxy contributes exactly its real spectrum and nothing synthetic derived from it. The splitter refuses to return a split that leaks a galaxy across the boundary.

from specsr.data.splits import get_training_split
train_idx, val_idx, path = get_training_split("data/paired_DR4_logR.npz")

Repository layout

src/specsr/          all library code (see ARCHITECTURE.md)
configs/             stage configs and W&B sweep definitions
scripts/             thin entry points: argument parsing and file IO only
tests/               unit tests plus checkpoint-reproduction guards
tutorials_for_user/  executable notebooks with bundled sample spectra
docs/                Sphinx documentation

Documentation is at https://aryana-haghjoo.github.io/specsr/, or build it locally with pip install "specsr[docs]" then sphinx-build -b html docs docs/_build/html.

Citation

Please cite the paper for the method, and the Zenodo record if you need to reference a specific version of the code:

@software{haghjoo2026specsr_code,
  author    = {Haghjoo, Aryana},
  title     = {specsr: physics-informed super-resolution of JWST/NIRSpec prism spectra},
  year      = {2026},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.21943196},
  url       = {https://doi.org/10.5281/zenodo.21943196},
  note      = {Concept DOI; resolves to the latest version}
}
@article{haghjoo2026specsr,
  title   = {Learning to See Sharper: A Physics-Informed Artificial Intelligence
             Framework for Super-Resolving Galaxy Spectra},
  author  = {Haghjoo, Aryana and Hemmati, Shoubaneh and Mobasher, Bahram and others},
  journal = {The Astrophysical Journal},
  year    = {2026},
  eprint  = {2603.18357},
  archivePrefix = {arXiv},
  primaryClass  = {astro-ph.GA}
}

License

MIT — see LICENSE.

Metadata

Release files for specsr 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for specsr 1.2.0
File Size Uploaded Provenance Actions
specsr-1.2.0.tar.gz 2.1 MB With provenance Details for specsr-1.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for specsr 1.2.0
File Interpreter ABI Platform Actions
specsr-1.2.0-py3-none-any.whl Python 3 none any Details for specsr-1.2.0-py3-none-any.whl

Total release size: 2.2 MB

Release files / specsr-1.2.0.tar.gz

Download URL specsr-1.2.0.tar.gz
Size 2.1 MB
Tags Source
SHA-256 checksum
How to use checksums
dc467a2f5c0f6c79d5874e7c902776f805fc68928140dd43698528441cd410df
BLAKE2b-256 checksum
How to use checksums
7e5c09de38424ef6346bd737df335e9de2a19e3712f45eb1e98cb41da393fa85
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / specsr-1.2.0-py3-none-any.whl

Download URL specsr-1.2.0-py3-none-any.whl
Size 177.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dde466980a9889b6b532ffa96bf5367aec81ccb001bf29594078113608072246
BLAKE2b-256 checksum
How to use checksums
4408e5d7528d5e6df8bb2b4c422940aea8623d13537f4a793ef90a2dfd31b6ca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Security for specsr 1.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for specsr-1.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page