Changelog¶
Notable changes to specsr-roman. Versions follow semantic
versioning; until 1.0 the public API may still move.
[Unreleased]¶
Added¶
tutorials/01_getting_started.ipynb— an executable walkthrough from install to the published numbers: one super-resolved spectrum, the redshift PDF and what its secondary modes mean, what photometry buys and why it must be noisy, and line recovery split by recoverability. Runs in about two minutes on a CPU. Committed with its outputs and rendered into the docs from those outputs, so a docs build never re-runs a model or republishes an unreviewed number.A 512-row tutorial subset of the dataset, on the Hub under
tutorial/(3.8 MB). Drawn from the held-out side of the canonical object-id split and sampled uniformly within it, so metrics computed on it are honest out-of-sample numbers over the population’s real mix of recoverable and undetectable lines. Built byscripts/make_tutorial_dataset.py.
Changed¶
Roman Medium-tier photometry only, everywhere.
grids.PHOT_TIERSnow offersmediumalone, andgrids.MAX_PHOT_BANDSrefuses an explicit band list longer than the three bands that fly with the grism. Wider tiers let a model read the redshift off an effectively complete simulated SED, which scores well and means nothing on the sky.The photometry ablation is Roman Medium-tier and ships.
specsr-roman evaluate ablationnow measures the published three-band head with and without its colours and sweeps the photometric noise, and writesphot_ablation.pngalongside the CSV.Corrected the grism-only redshift number. The README, the model card, the quickstart and the
RomanPipelinedocstring reported a figure taken from a masking ablation on a different, superseded head. Measured directly on the published chain,phot=Nonegives NMAD 0.014 / 26 % catastrophic over the same 7,334-row held-out split. All four now carry the measured number, and say plainly thatphot=Noneis mean imputation on a head trained with photometry rather than a grism-only model — so it is not a measurement of the information floor either.Docs render notebooks via
myst-nb(which replacesmyst-parserin thedocsextra and loads it itself).
[0.1.0] — 2026-08-26¶
First packaged release. The science and the trained models predate it; this version turns a working set of scripts into an installable, tested library.
Added¶
specsr-romanpackage with a one-way dependency structure —models→data→inference→training→evaluation. Training and evaluation shareinference.build_sr2_input, so all three paths assemble SR2’s input identically.RomanPipeline.from_pretrained()— the published three-stage chain in four lines, fetching weights from the Hugging Face Hub on first use. Accepts a single spectrum or a batch; returns super-resolved flux, per-pixel uncertainty, the full P(z), and per-line presence.specsr-romanCLI —extract,train,predict,evaluate,info.Typed configs (
specsr_roman.config) withconfigs/{sr1,zhead,sr2}.yamlreproducing the published chain exactly. Unknown keys raise rather than silently doing nothing.Checkpoint resolution accepting a local path, a bare Hub run name, or
org/repo:name, so nothing hard-codes a machine layout.Test suite (97 tests) covering loss behaviour, not just shapes: that the hallucination penalty leaves recoverable lines alone, that the flux- conserving rebin preserves a narrow line, that a descending wavelength grid is caught, that the group split cannot leak an object across train/test.
ARCHITECTURE.md— the design and the reasoning behind each choice.
Changed¶
Extraction, training and evaluation scripts became library modules. The old
sys.pathcross-imports between sibling training directories are gone; everything now lives underspecsr_roman.*with a one-way dependency structure.Photometric band selection is now a named tier (
medium,deep,all) applied at dataset load, rather than an ad-hoc in-place array slice after construction. The dataset and the model it feeds can no longer disagree about band count.Split records now live beside the dataset rather than inside a training directory. Group-split membership is unaffected — it is a pure hash of the object id — and was verified bit-identical to the previously recorded split.
Figure code moved to
specsr_roman.evaluation.figureswith amake_figuresdispatcher. Output verified byte-identical to the figures in the manuscript.
Fixed¶
These are fixes relative to the previous script-based workflow — bugs that were live in this repository, not in unreleased code.
The prior-dominance audit now runs, and gives a real answer. It had been unusable on OU2024: the Diffsky SEDs carry an internal flux scale (~1e-20) unrelated to the extraction’s units, so the injected off-manifold perturbation was numerically invisible once added to the LR spectrum. That pinned the response exponent at exactly 0.000, which reads as “the model recites the prior” and is indistinguishable from a real, catastrophic result. Injection now goes through a fitted calibration bridge (the least-squares scale between the LSF-smoothed truth and the observation). The published SR1 scores r ≈ 0.45.
An unanchored
data/rule in.gitignorematchedsrc/specsr_roman/data/, which would have excluded the data subpackage from git, fromruff, and from any built wheel —import specsr_romansucceeding whilespecsr_roman.datadid not exist. All artefact rules are now anchored to the repository root.Photometry standardisation statistics are computed from the train split only, via
data.photometry.standardization_stats.The photometry ablation no longer reports a “spectrum zeroed” row. Zeroing the spectral channels is out of distribution for SR1 — unlike masking a photometric band, which standardises to a value the network sees constantly — and it scores worse than masking every band, measuring the OOD input rather than the photometry’s contribution.
np.trapz/np.trapezoidhandled across the NumPy 2.0 rename.
Known limitations¶
Results are on the Diffsky manifold; see README → Limitations.
Anti-prior augmentation is implemented but not used by the published SR1 — it improves data-faithfulness at the cost of absolute line recovery.
The ~5 % catastrophic redshift rate is a physical information floor for a single-line grism, not a tuning target.