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.
[!IMPORTANT] The model does not predict absolute flux scale. Each spectrum is standardised independently during training, so what is learned is a mapping from shape to shape, and output is returned on the input's scale. Compare in normalised units.
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 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.
- 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.
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 specsr-1.0.2.tar.gz.
File metadata
- Download URL: specsr-1.0.2.tar.gz
- Upload date:
- Size: 2.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
840fd4e958db7ea1b6cbebe75273200a9661992edb45dcde5bc2a37dc3e3d52d
|
|
| MD5 |
91582ae3a4631f1a3495252efe4f761d
|
|
| BLAKE2b-256 |
6ac0847b2d76518ba7646401631c67eb82bd822c7d3b8789be699b71e9a27cea
|
Provenance
The following attestation bundles were made for specsr-1.0.2.tar.gz:
Publisher:
publish.yml on aryana-haghjoo/specsr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
specsr-1.0.2.tar.gz -
Subject digest:
840fd4e958db7ea1b6cbebe75273200a9661992edb45dcde5bc2a37dc3e3d52d - Sigstore transparency entry: 2473411334
- Sigstore integration time:
-
Permalink:
aryana-haghjoo/specsr@6601355cacc0a04b9a2b2677c6020f73144a2e1b -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/aryana-haghjoo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6601355cacc0a04b9a2b2677c6020f73144a2e1b -
Trigger Event:
push
-
Statement type:
File details
Details for the file specsr-1.0.2-py3-none-any.whl.
File metadata
- Download URL: specsr-1.0.2-py3-none-any.whl
- Upload date:
- Size: 168.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe91d8ef7b59d9ff63c23e24336c513a04ec480a9cc53d4dd44a19c45635d41f
|
|
| MD5 |
c10105771293fb272b956d749a9012e4
|
|
| BLAKE2b-256 |
c46354c91be79e9b26630cddd01181df1ab1481b3000f899d01502ce07f0818a
|
Provenance
The following attestation bundles were made for specsr-1.0.2-py3-none-any.whl:
Publisher:
publish.yml on aryana-haghjoo/specsr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
specsr-1.0.2-py3-none-any.whl -
Subject digest:
fe91d8ef7b59d9ff63c23e24336c513a04ec480a9cc53d4dd44a19c45635d41f - Sigstore transparency entry: 2473411345
- Sigstore integration time:
-
Permalink:
aryana-haghjoo/specsr@6601355cacc0a04b9a2b2677c6020f73144a2e1b -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/aryana-haghjoo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6601355cacc0a04b9a2b2677c6020f73144a2e1b -
Trigger Event:
push
-
Statement type: