pygspice 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygspice-2.0.0/.gitignore +15 -0
- pygspice-2.0.0/CHANGELOG.md +97 -0
- pygspice-2.0.0/CITATION.cff +28 -0
- pygspice-2.0.0/LICENSE +674 -0
- pygspice-2.0.0/PKG-INFO +72 -0
- pygspice-2.0.0/README.md +57 -0
- pygspice-2.0.0/pyproject.toml +91 -0
- pygspice-2.0.0/src/gspice/__init__.py +80 -0
- pygspice-2.0.0/src/gspice/_blocks.py +308 -0
- pygspice-2.0.0/src/gspice/_datasets.py +237 -0
- pygspice-2.0.0/src/gspice/_diagnostics.py +708 -0
- pygspice-2.0.0/src/gspice/_linalg.py +549 -0
- pygspice-2.0.0/src/gspice/_model.py +1690 -0
- pygspice-2.0.0/src/gspice/_predict.py +1157 -0
- pygspice-2.0.0/src/gspice/_repair.py +460 -0
- pygspice-2.0.0/src/gspice/_spectra.py +511 -0
- pygspice-2.0.0/src/gspice/legacy/__init__.py +30 -0
- pygspice-2.0.0/src/gspice/legacy/_errors.py +2 -0
- pygspice-2.0.0/src/gspice/legacy/djs_maskinterp.py +152 -0
- pygspice-2.0.0/src/gspice/legacy/matrixUtils.py +204 -0
- pygspice-2.0.0/src/gspice/legacy/specUtils.py +464 -0
- pygspice-2.0.0/src/gspice/py.typed +0 -0
- pygspice-2.0.0/tests/conftest.py +26 -0
- pygspice-2.0.0/tests/golden/README.md +83 -0
- pygspice-2.0.0/tests/golden/_golden.py +244 -0
- pygspice-2.0.0/tests/golden/generate_golden.py +983 -0
- pygspice-2.0.0/tests/golden/golden_D1_gaussian_estimate.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D1_gp_interp.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D1_masks.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D1_scale.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D2_gaussian_estimate.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D2_gp_interp.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D2_masks.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D2_scale.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D3_gaussian_estimate.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D3_gp_interp.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D3_masks.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D3_scale.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_D4_masks.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_E.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_linalg_300.npz +0 -0
- pygspice-2.0.0/tests/golden/golden_linalg_50.npz +0 -0
- pygspice-2.0.0/tests/golden/inputs_D1.npz +0 -0
- pygspice-2.0.0/tests/golden/inputs_D2.npz +0 -0
- pygspice-2.0.0/tests/golden/inputs_D3.npz +0 -0
- pygspice-2.0.0/tests/golden/inputs_D4.npz +0 -0
- pygspice-2.0.0/tests/golden/inputs_E.npz +0 -0
- pygspice-2.0.0/tests/golden/inputs_MAT.npz +0 -0
- pygspice-2.0.0/tests/golden/manifest.json +4982 -0
- pygspice-2.0.0/tests/golden/test_golden.py +305 -0
- pygspice-2.0.0/tests/golden/test_new_api.py +292 -0
- pygspice-2.0.0/tests/legacy/test_behaviour_changes.py +450 -0
- pygspice-2.0.0/tests/oracle.py +162 -0
- pygspice-2.0.0/tests/r26/__init__.py +1 -0
- pygspice-2.0.0/tests/r26/djs_maskinterp.py +81 -0
- pygspice-2.0.0/tests/r26/matrixUtils.py +122 -0
- pygspice-2.0.0/tests/r26/repairUtils.py +429 -0
- pygspice-2.0.0/tests/r26/specUtils.py +217 -0
- pygspice-2.0.0/tests/test_blocks.py +442 -0
- pygspice-2.0.0/tests/test_contracts.py +781 -0
- pygspice-2.0.0/tests/test_datasets.py +216 -0
- pygspice-2.0.0/tests/test_diagnostics.py +639 -0
- pygspice-2.0.0/tests/test_docs.py +89 -0
- pygspice-2.0.0/tests/test_fit.py +923 -0
- pygspice-2.0.0/tests/test_linalg.py +600 -0
- pygspice-2.0.0/tests/test_model.py +623 -0
- pygspice-2.0.0/tests/test_predict.py +1229 -0
- pygspice-2.0.0/tests/test_readme.py +17 -0
- pygspice-2.0.0/tests/test_repair.py +1023 -0
- pygspice-2.0.0/tests/test_spectra.py +264 -0
- pygspice-2.0.0/tests/test_typing.py +195 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
dist
|
|
2
|
+
.vscode
|
|
3
|
+
# The npm packages and cache of the site, and the API pages of docs/scripts/api.py
|
|
4
|
+
docs/node_modules/
|
|
5
|
+
docs/.astro/
|
|
6
|
+
docs/src/content/docs/reference/
|
|
7
|
+
# The 2021 draft of the paper, kept out of the repository
|
|
8
|
+
paper/
|
|
9
|
+
# Local environments and caches
|
|
10
|
+
.venv/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.coverage
|
|
13
|
+
__pycache__/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.hypothesis/
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 2.0.0 - 2026-10-29
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Golden tests in `tests/golden/`: the outputs of every public function of the 2022 package (commit `1fbab9f`) on synthetic inputs, and tests that compare an implementation with them.
|
|
8
|
+
- Continuous integration on Linux with Python 3.11 to 3.15, on macOS and Windows with Python 3.11 and 3.15, and on the oldest supported numpy and scipy.
|
|
9
|
+
- A CI job that builds the wheel and the sdist, checks that the sdist holds the sources and tests and that the wheel holds `py.typed` and no tests, and runs a smoke test of the wheel in a clean environment.
|
|
10
|
+
- The package is on PyPI as `pygspice`, because PyPI does not allow the name `gspice`: `pip install pygspice`. The import name is `gspice`. Before you install it, run `pip uninstall gspice` if you installed GSPICE from GitHub, because both packages write the same files.
|
|
11
|
+
- A workflow that, for each tag `vX.Y.Z`, runs CI, uploads the wheel and the sdist to PyPI once the lead approves, and publishes a GitHub release with them and the CHANGELOG section of X.Y.Z. It checks that the tag names the version of the built package.
|
|
12
|
+
- `pyproject.toml`: `pip install .` installs the package. It requires Python 3.11 or later, numpy 1.26 or later and scipy 1.11 or later.
|
|
13
|
+
- `gspice.__version__`, which is `2.0.0`.
|
|
14
|
+
- `CITATION.cff`, the citation metadata for the software and the paper, which the sdist holds.
|
|
15
|
+
- The licence is declared as GPL-3.0-or-later, the GPL v3 of the 2022 code in its "or later" form.
|
|
16
|
+
- Type checks with mypy in strict mode for the code outside `gspice.legacy`.
|
|
17
|
+
- A test coverage floor of 90% for the code outside `gspice.legacy`.
|
|
18
|
+
- pre-commit hooks that run ruff.
|
|
19
|
+
- Log records on the `gspice` logger: DEBUG lines on the time and size of the work of the main functions, INFO lines on the clipping passes of `fit`, and a WARNING from `fit` for each clipping pass whose threshold exceeds the in-sample ceiling of |z|. The package adds a `logging.NullHandler` to the logger, so the application decides where the records go.
|
|
20
|
+
- A documentation site in `docs/`, built with Sphinx and deployed to GitHub Pages, with a quickstart, tutorials on fitting, pixelwise prediction, infilling, repair, calibration, the low-rank and noise-aware models, saving and loading, and migrating from the 2022 interface, background pages on the method, prediction, repair, fitting and diagnostics, a glossary, an API reference of every public name, and the GSPICE logo. The tutorials work on simulated LAMOST-like spectra from `docs/scripts/spectra.py`, and `docs/scripts/figures.py` makes their figures.
|
|
21
|
+
- `benchmarks/run.py`, which times `pixelwise`, `infill`, `fit_blocks`, `repair`, `fit`, the noise models, the 2022 `gp_interp` and the 2022 Schur route against `solve_pattern`, and prints the timings and the setup as JSON.
|
|
22
|
+
- `gspice.scale`, `gspice.unscale` and `gspice.snr`. `scale` interpolates each spectrum over its bad pixels and scales it to unit mean noise, `unscale` returns scaled values and variances to flux units, and `snr` gives the median signal-to-noise ratio of each spectrum.
|
|
23
|
+
- `gspice.Model`, which holds the mean, the covariance and the training count of each S/N bin, and `gspice.save` and `gspice.load`, which write and read a model as one .npz file.
|
|
24
|
+
- `gspice.pixelwise`, which predicts each pixel of each spectrum from the pixels farther than `nguard` from it, and its result `gspice.Prediction`. A model keeps the precision matrix and the guard weights of each bin after their first use.
|
|
25
|
+
- `gspice.simulate`, which draws synthetic continuum-normalized spectra for tests and examples, and its result `gspice.Simulation`. The spectra have absorption lines whose depths follow two latent parameters in two populations, Gaussian noise, and optional cosmic rays, bad columns and shifted blocks. With `gaussian=True` and no artifacts they are exactly Gaussian.
|
|
26
|
+
- `gspice.infill`, which replaces chosen pixels of each spectrum by their Gaussian conditional mean given the other pixels, and its result `gspice.Repaired`. It reports the replaced and ignored pixels and χ², with `covariance=True` the conditional covariance of the replaced pixels of each spectrum, and with a `numpy.random.Generator` as `rng` a draw from the conditional distribution in `Repaired.draws`. Without `rng`, spectra of one S/N bin with the same replaced pixels share one factorization of the precision matrix at the pixels that all of them exclude, also where each spectrum has a few bad pixels of its own; `repair` and `calibration` take the same route where their patterns allow it.
|
|
27
|
+
- `gspice.fit`, which fits a model to training spectra with the iterative outlier clipping of paper Alg. 4, and returns the model and the final training mask.
|
|
28
|
+
- `gspice.finite_sample_factor`, which gives f_s(N_s, N_k, N_*), the mean χ² per predicted pixel of a held-out Gaussian spectrum when a model fitted to N_s spectra predicts N_* pixels from N_k others.
|
|
29
|
+
- The option `inflate` of `gspice.pixelwise` and `gspice.infill`, which multiplies the variances and covariances of a mean-centred, unweighted model by f_s(N_s, N_k, 1). The field `Repaired.fs` holds the factor of each spectrum by which `chi2 / dof` is divided, so that `chi2 / (dof * fs)` has the mean 1 for held-out Gaussian spectra of such a model, with or without `inflate`.
|
|
30
|
+
- `gspice/py.typed`, the PEP 561 marker, so that type checkers read the annotations of an installed `gspice`. The functions of `gspice.legacy` keep their 2022 signatures without annotations.
|
|
31
|
+
- `gspice.fit_blocks`, which computes from spectra without artifacts a χ² threshold for each block of consecutive pixels and each S/N bin (paper section 3.2), and returns the model with them. `gspice.Blocks` holds the blocks and their thresholds in the new field `Model.blocks`, which `save` and `load` keep.
|
|
32
|
+
- `gspice.noise_audit`, which compares the residuals of `gspice.pixelwise` with the reported noise at each pixel. It returns rho, the root mean of (f − f̂)² ivar over the spectra that are good at the pixel; on spectra not used in the fit and away from bad runs longer than nguard, rho² has a mean above 1 even where ivar is right.
|
|
33
|
+
- `gspice.calibration`, which predicts a run or a random set of n good pixels of each held-out spectrum from its other good pixels, for each of several sizes n, with masks drawn independently of the data, and its result `gspice.Calibration`. `Calibration` holds χ², n and the finite-sample factor f_s of each prediction, and also takes the results of `infill` and `pixelwise`. Its methods give the mean of χ²/(n·f_s) and its standard error, the fraction of χ²/f_s above a quantile of the χ² distribution with n degrees of freedom, and the normal scores of a QQ plot, for all spectra or a selection of them. An error of a prediction names the row of its spectrum in `flux`.
|
|
34
|
+
- `gspice.repair`, which detects and replaces bad pixels with the procedure that the paper validates on simulated spectra: two pixelwise passes, a block pass with the thresholds of `fit_blocks`, an exclusion of the pixels around extended artifacts, and a final `infill`. The second pixelwise pass tests again each pixel that the first one flagged. The field `Repaired.blocks` holds the blocks that the block pass flagged in each spectrum.
|
|
35
|
+
- The option `rank` of `gspice.fit`, which fits a low-rank model: the covariance C = V diag(values) Vᵀ + diag(d) holds the K leading eigenvectors V and eigenvalues of the sample covariance, and d keeps its diagonal. Where K ≤ npix/80, Lanczos finds them, with a check that falls back to the eigendecomposition of the K pairs and logs it at INFO. The clipping passes use the same rank, so they also run with fewer spectra than pixels. `gspice.LowRank` holds V, the values and d, and `save` and `load` keep it. A model computes the precision matrix of a low-rank covariance by the Woodbury identity, without forming C, and raises `numpy.linalg.LinAlgError` where its condition bound κ_W exceeds 1e13. `inflate` needs a dense model, and `Repaired.fs` and `Calibration.fs` are 1 for a low-rank one.
|
|
36
|
+
- The option `snr_bins` of `gspice.fit`, which fits a model of several S/N bins: either their number n, with edges at the quantiles that give each bin the same count of the spectra that `fit` uses before clipping, or the interior edges. Each bin runs the clipping passes and the final fit on its own spectra, so it gets its own mask, mean, covariance and training count, as `fit` gives for those spectra alone.
|
|
37
|
+
- The option `noise` of `gspice.fit`, which fits a noise model in flux units. Its covariance is that of the noise-free flux, from an estimator that is unbiased with per-pixel masks, weights and the ivar of each spectrum, with its negative eigenvalues set to 0; with `rank=K`, its K leading eigenpairs plus the diagonal of the other eigenpairs, with their negative eigenvalues set to 0. The clipping passes run as without `noise`. The new field `Model.noise` marks such a model, and `save` and `load` keep it. `pixelwise`, `infill`, `repair`, `fit_blocks`, `calibration` and `noise_audit` condition each spectrum on that covariance plus its own noise variances, 1/ivar at good pixels and 1/a_s² at bad pixels, with a_s² the mean ivar of the good pixels, and form its precision matrix once per call, or, for a dense noise model in a call that forms no precision matrix for other steps, such as `infill` and `calibration`, only its Cholesky factor. `pixelwise` of a noise model computes each mean from its precision matrix times the spectrum, so an outlier within nguard of a pixel cancels in its mean only to rounding, linearly in the outlier: 9.3e-10 in z at 1e6σ in the review of PR #103. Their infills of a noise model with `rank=K` use the K eigenpairs and the diagonal plus the noise variances instead, at about npix K² flops per pattern, without the precision matrix; they raise where κ_K = 1 + λ_max(Λ^½ Vᵀ D_s⁻¹ V Λ^½) exceeds 1e13, which accepts every C_s that κ_W accepts. `noise` takes no `center` or `snr_bins`, `inflate` needs a model without noise, and `Repaired.fs` and `Calibration.fs` are 1 for a noise model.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- The documentation site is built with Astro Starlight instead of Sphinx. Its API pages come from the docstrings, as before. Page addresses end in `/` instead of `.html`, for example `https://joshspeagle.github.io/GSPICE/start/install/`, and the anchors of the API and glossary entries are unchanged.
|
|
42
|
+
- The documentation site has the visual design of `docs/brand.md`: dark and light themes on a navy header, the Archivo and IBM Plex Mono fonts, square corners, a new logo and favicon drawn in pixel cells, output blocks joined to their code, and framed figures.
|
|
43
|
+
- The documentation site opens with a Getting started group: Is GSPICE right for my data?, Install, Quickstart, Prepare your spectra, and What you get back. The home page has an interactive figure that predicts the pixels under a block that you drag over a spectrum. The installation and quickstart pages moved to `start/install/` and `start/quickstart/`, and their old addresses redirect there.
|
|
44
|
+
- The documentation site has a Guides group of seven task pages on simulated spectra, which need no download: Fill known bad pixels, Find outliers, Find and repair artifacts, Choose a model, Check your model, Save and load, and Troubleshooting. They replace the tutorials on pixelwise prediction, infilling, repair, calibration, the low-rank and noise-aware models, and saving, whose old addresses redirect to them. The glossary adds artifact, clean spectrum, flagged pixel, outlier, scaled model and shifted segment.
|
|
45
|
+
- The docstrings, and so the API pages, use the terms of the glossary and show their equations as rendered maths. `README.md` has a figure of the quickstart, an example, badges and links to the pages of the site.
|
|
46
|
+
- The documentation site has a Concepts group of eight pages in place of the six Background pages: The model, Fitting, Prediction, Held-out uncertainty, Detection, Diagnostics, Numerics and Glossary. They hold the ideas, the equations and their limits, with new figures drawn from `gspice.simulate` by `docs/scripts/concepts.py`, and no code to run. Held-out uncertainty and Numerics are new, Numerics with benchmark times. The glossary adds a symbol table and terms such as conditional mean, covariance, ivar and S/N, and keeps its anchors. The old Background addresses redirect to the new pages.
|
|
47
|
+
- The documentation site has interactive explainers: on The model, a covariance explorer, a two-pixel explainer and the full mask explainer; in Find outliers, the guard window; and in Find and repair artifacts, the steps of `repair`. A link to a glossary entry shows the entry in a card on hover or keyboard focus.
|
|
48
|
+
- The documentation site replaces its two tutorials with four pages. A survey end to end runs GSPICE on the 10000 simulated LAMOST-like spectra of `docs/scripts/spectra.py`, with figures in the style of the site. Migrate from the 2022 package gives in one table the new function, the outputs and the units for each 2022 function, then the deprecation timeline. Cite GSPICE gives the paper, `CITATION.cff` and the data of the worked example, and the Changelog page shows this file. The old tutorial addresses redirect to the new pages.
|
|
49
|
+
|
|
50
|
+
### Deprecated
|
|
51
|
+
|
|
52
|
+
- An access to one of the 11 functions of the 2022 package through `gspice`, as `gspice.<name>` or `from gspice import <name>`, emits a `DeprecationWarning`. It names the replacement and the removal of the name in 3.0.0. The access returns `gspice.legacy.<name>`, which keeps the 2022 results, except for the behaviour changes below, and does not warn. Type checkers report `gspice.<name>` as an unknown attribute.
|
|
53
|
+
- `gspice.standard_scale`: use `gspice.scale`.
|
|
54
|
+
- `gspice.covar` and `gspice.covar_iter_mask`: use `gspice.fit`.
|
|
55
|
+
- `gspice.get_chimask` and `gspice.gp_interp`: use `gspice.pixelwise`.
|
|
56
|
+
- `gspice.gaussian_estimate`: use `gspice.infill`.
|
|
57
|
+
- `gspice.cholesky_inv`, `gspice.submatrix_inv`, `gspice.submatrix_inv_mult`, `gspice.maskinterp1` and `gspice.maskinterp`: use `gspice.legacy.<name>`.
|
|
58
|
+
|
|
59
|
+
### Removed
|
|
60
|
+
|
|
61
|
+
- The IDL code in `pro/` and the Julia code in `julia/`.
|
|
62
|
+
- The notebooks and notes of 2021 and 2022 in `notebooks/` and `notes/`, and the 2021 draft of the paper in `paper/`.
|
|
63
|
+
- `setup.py`, which `pyproject.toml` replaces.
|
|
64
|
+
- The egg in `dist/` and the 2022 tests in `gspice/tests/`, which could not run and which the golden tests replace.
|
|
65
|
+
- The import of astropy, which the 2022 code did not use.
|
|
66
|
+
- The 10 prints of `gspice.legacy`, which reported progress, timings, shapes and notices such as "imask does not remove any rows or columns." `covar(checkmean=True)` still prints its check of the column means.
|
|
67
|
+
- The LAPACK message that `cholesky_inv` printed for a 0 × 0 matrix.
|
|
68
|
+
|
|
69
|
+
### Behaviour changes
|
|
70
|
+
|
|
71
|
+
- The second pixelwise pass of `repair` tests each pixel again against its prediction with the replaced pixels infilled. A pixel above `nsigma_replace` in the first pass stays flagged only while it exceeds `nsigma_ignore` there, and the exclusion of step 4 counts the new sets. The paper and r26 `gp_repair` keep every such pixel, which replaced artifact-free pixels whose first-pass prediction a strong artifact had disturbed; design decision A30 gives the measurements.
|
|
72
|
+
- Step 5 of `repair` on a dense noise model agrees with `infill` to rounding, not bit for bit, where steps 1 to 4 form the precision matrix of the spectrum: `infill` then uses its Cholesky factor. In the test of the steps, flux differed by 1.4e-14σ.
|
|
73
|
+
- The block χ² of `fit_blocks` and `repair` reads the guard pixels of each block, which the earlier unreleased code never read. An outlier in a guard cancels only to rounding, so χ²_A changes linearly with its size: by up to 6e-8 at κ 1e8 and 1e4σ, and by 8.6 at κ 1e10 and 1e10σ (measured in PR #99).
|
|
74
|
+
- The golden tests compare 11 outputs at a relative tolerance looser than 1e-10: 1e-9 for 7 outputs and 1e-8 for 4. These outputs come from ill-conditioned inputs, on which the 2022 results differ from a direct Cholesky solve by up to 7.6e-10.
|
|
75
|
+
- The 2022 modules `gspice.specUtils`, `gspice.matrixUtils` and `gspice.djs_maskinterp` moved to `gspice.legacy.specUtils`, `gspice.legacy.matrixUtils` and `gspice.legacy.djs_maskinterp`, and the unused `gspice.gspiceMain` is deleted. Imports of the old module paths fail, and pickles that name the old paths no longer load. To migrate, insert `legacy.` into the module path, for example `from gspice.legacy.specUtils import standard_scale`.
|
|
76
|
+
- `gspice.__all__` holds the new public names and `legacy`, so `from gspice import *` binds them. It no longer binds the 11 functions and the 3 modules of the 2022 package. It can shadow names such as `load` and `save` of an earlier `from numpy import *`. To migrate, use `from gspice.legacy import *`, which binds the same 14 names as the 2022 star import, without a warning.
|
|
77
|
+
- The 2022 asserts of `gspice.legacy` raise `_LegacyError`, a subclass of `AssertionError` and `ValueError`, with a message that names the argument. An `except ValueError` clause now catches them, and the checks also run under `python -O`.
|
|
78
|
+
- `gp_interp` accepts `irange` as a list, a tuple or an array of at least two integers of any integer type, and raises unless 0 <= `irange[0]` <= `irange[1]` <= npix - 1. The 2022 code rejected a 2-element `irange` and a uint64 array, and for a negative start with `irange[1]` = npix - 1 it returned leading columns of zeros. A numpy bool in `irange[0]` or `irange[1]` raises `TypeError`, and spectra without pixels raise.
|
|
79
|
+
- `gp_interp` raises for a negative `nguard`, where the 2022 code predicted each pixel from itself. Under numpy 2, fixed-width numpy integers now work for `nguard`, where the 2022 code gave wrong windows or raised OverflowError or TypeError. A numpy bool or an array of one or more dimensions raises `TypeError` for `nguard`.
|
|
80
|
+
- When `bruteforce` is False and `imask` keeps every row, `submatrix_inv` and `submatrix_inv_mult` return a copy of `Minv` and `MinvY`. The 2022 code returned the argument itself, so a later change to the result changed the caller's array.
|
|
81
|
+
- `gp_interp` with `bruteforce=True` returns `pred` and `predvar` in the layout of the default path, where the 2022 code raised ValueError. The golden tests compare them with the 2022 outputs of the default path at the tolerances of those outputs, which are 1e-8 for 4 of them.
|
|
82
|
+
- In an array with one good entry, `maskinterp1` sets a non-finite value at a bad entry to the good value, and so do `maskinterp` and `djs_maskinterp.average_bilinear`, which call it. The 2022 code gave NaN there. `standard_scale` spread that NaN to a whole column of Dvec, and `get_chimask` and `covar_iter_mask` then raised ValueError.
|
|
83
|
+
- `standard_scale` ignores a non-finite ivar at a bad pixel. The 2022 code made the refscale of that spectrum NaN, and with it every value of Dvec and refmean, so `get_chimask` and `covar_iter_mask` raised ValueError.
|
|
84
|
+
- `standard_scale` and `get_chimask` raise `_LegacyError` for a spectrum without a good pixel, and name its row. `covar_iter_mask` raises it for a kept spectrum that its mask or the clipping masks completely, and names its row in `flux`. The 2022 code returned NaN or raised another error.
|
|
85
|
+
- `covar_iter_mask` accepts `mask=None`, which marks the pixels where ivar == 0, also for `maxbadpix`. The 2022 code raised numpy's AxisError.
|
|
86
|
+
- `scale` raises ValueError for a non-finite flux at a good pixel, a non-finite or negative ivar at a pixel not in `mask`, and zero spectra without `refmean`. For such inputs, the 2022 `standard_scale` returned NaN or a wrong refscale.
|
|
87
|
+
- `scale` counts a pixel with ivar = 0 as bad also where `mask` is given. It interpolates the flux of such a pixel and leaves the pixel out of refscale. The 2022 `standard_scale` with a mask used that flux and counted the 0 in the mean ivar.
|
|
88
|
+
- `scale` casts flux to float64 before it interpolates. The 2022 `standard_scale` interpolated in the dtype of the flux, so it truncated the interpolated values of integer flux and rounded those of float32 flux to float32.
|
|
89
|
+
- `scale` checks and computes a long double flux or ivar as float64. It raises ValueError for a long double beyond the float64 range at a good pixel, and an ivar that rounds to 0 in float64 marks a bad pixel. The 2022 `standard_scale` computed in long double and returned a finite result for such values.
|
|
90
|
+
- `scale` and `snr` raise ValueError for a spectrum without a good pixel, and name its row. For such a spectrum, the 2022 `standard_scale` returned NaN in every value of Dvec and refmean.
|
|
91
|
+
- `pixelwise` computes the conditional variances through the precision matrix, where the 2022 `gp_interp` used the Schur updates of a precomputed inverse. On the golden data set D3, whose covariance has the condition number 8.6e4, the 2022 predvar differs from a 60-digit reference by up to 7.6e-10 at nguard 5 and 2.7e-10 at nguard 20, relative. `pixelwise` differs by at most 1.7e-13 and 8.7e-14.
|
|
92
|
+
- `infill` computes the conditional covariance through the precision matrix, where the 2022 `gaussian_estimate` used the Schur updates of a precomputed inverse. On D3, the 2022 predcovar differs from a 60-digit reference by up to 3.0e-10 relative on the diagonal, and `infill` by at most 8.8e-14.
|
|
93
|
+
- `fit` masks the flags of every clipping pass, as paper Alg. 4 does. The 2022 `covar_iter_mask` masked only the flags of the last two passes; `fit(cumulative=False)` keeps that rule. On the golden data sets D1 to D4, the final mask of the default `fit` differs from the 2022 mask in 157, 152, 106 and 8 entries.
|
|
94
|
+
- `fit` flags a pixel whose |z| exceeds the threshold. The 2022 `get_chimask` also flagged a pixel whose |z| equals it.
|
|
95
|
+
- `fit` drops a spectrum that has no good pixel, or that a clipping mask covers completely. For such a spectrum, the 2022 `covar_iter_mask` returned a covariance of NaN or raised an error.
|
|
96
|
+
- `fit` needs at least npix + 1 spectra for a mean-centred model, and a good pixel in one of them at every pixel, and raises ValueError otherwise. The 2022 `covar_iter_mask` accepted npix spectra, whose covariance is singular, and then raised LinAlgError or flagged most pixels. It filled a pixel that is bad in every spectrum by interpolation, which also makes the covariance singular; on D1 it then raised LinAlgError.
|
|
97
|
+
- `fit` counts a pixel with ivar = 0 as bad, also against `maxbadpix`. The 2022 `covar_iter_mask` counted only the pixels in its mask.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: If you use this software, please cite the paper below.
|
|
3
|
+
title: GSPICE
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
date-released: '2026-10-29'
|
|
6
|
+
license: GPL-3.0-or-later
|
|
7
|
+
repository-code: https://github.com/joshspeagle/GSPICE
|
|
8
|
+
url: https://joshspeagle.github.io/GSPICE/
|
|
9
|
+
abstract: >-
|
|
10
|
+
GSPICE models spectra on a common wavelength grid as a multivariate Gaussian with
|
|
11
|
+
an empirical covariance, and predicts any set of pixels from the others. The
|
|
12
|
+
prediction can replace bad pixels, and the distance of a pixel from its prediction
|
|
13
|
+
can flag artifacts.
|
|
14
|
+
authors: &authors
|
|
15
|
+
- family-names: Finkbeiner
|
|
16
|
+
given-names: Douglas P.
|
|
17
|
+
- family-names: Speagle
|
|
18
|
+
given-names: Joshua S.
|
|
19
|
+
- family-names: Karim
|
|
20
|
+
given-names: Tanveer
|
|
21
|
+
preferred-citation:
|
|
22
|
+
type: article
|
|
23
|
+
title: Data-Driven Stellar Spectral Modelling with GSPICE
|
|
24
|
+
authors: *authors
|
|
25
|
+
journal: arXiv e-prints
|
|
26
|
+
year: 2025
|
|
27
|
+
url: https://arxiv.org/abs/2511.16754
|
|
28
|
+
doi: 10.48550/arXiv.2511.16754
|