Converters: SACC→2pt-FITS (byte-compared) + SACC↔OneCovariance glue#249
Draft
cailmdaley wants to merge 3 commits into
Draft
Converters: SACC→2pt-FITS (byte-compared) + SACC↔OneCovariance glue#249cailmdaley wants to merge 3 commits into
cailmdaley wants to merge 3 commits into
Conversation
…sis_fitting
Add sp_validation.twopoint_convert.sacc_to_twopoint_fits, converting an analysis
SACC into the CosmoSIS 2pt-FITS that 2pt_like (and Sacha's rho/tau
2pt_like_xi_sys fork) reads. Output reproduces today's cosmo_inference
cosmosis_fitting.py assembly HDU-for-HDU and byte-for-byte: NZDATA, XI_PLUS/MINUS,
CELL_EE, the blocked COVMAT (STRT_i offsets) and separate COVMAT_CELL, and the
TAU_{0,2}_PLUS + verbatim RHO_STATS tables.
The data vector and covariance are permuted from SACC's pair-major order to the
2pt-FITS type-major layout via s.indices. The tau covariance is laid in as one
contiguous [tau_0+; tau_2+] block, preserving the tau_0<->tau_2 cross-correlation
that covdat_to_fits carries. Rho/tau HDUs need the rho/tau sidecar FITS: the
RHO_STATS varrho_* variance columns are not stored in the analysis SACC, so the
converter copies them verbatim (never fabricates them); xi, Cl, n(z) and the
covariance are fully reconstructed from SACC alone.
Tests:
- test_twopoint_convert.py: byte-equal vs current cosmosis_fitting.py builders on
deterministic synthetic inputs for all three product shapes (plain xi; xi+Cl;
xi+rho/tau), plus the tau_0<->tau_2 cross-correlation and perturbation teeth.
- test_twopoint_convert_realdata.py (skipif on candide paths): build a SACC from a
real product's own contents, convert, byte-compare vs the current writer.
Observed byte-equal for SP_v1.4.6_leak_corr and a glass_mock sibling; the stale
on-disk files differ only by an extra CELL_BB HDU (older script version) and
~1e-17 float noise on bin edges, documented and guarded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add sp_validation.one_covariance_io, the two small pieces of glue between the SACC layout and OneCovariance (which knows nothing of SACC and only exchanges files): - write_nz / nz_table / nz_config_stanza: the source_i NZ tracers of an analysis SACC -> OneCovariance's combined whitespace n(z) file (column 0 = shared z grid, one n(z) column per tomographic bin, no bin edges) plus the [redshift] config stanza pointing at it. Config keys verified against upstream OneCovariance config.ini (zlens_directory/zlens_file/value_loc_in_lensbin); the UNIONS template (cosmo_val/pseudo_cl.py._modify_onecov_config) uses the z_directory alias, exposed via dir_key. Fails fast on missing bins or disagreeing z grids. - covariance_blocks: OneCovariance's flat covariance_list_*.dat output -> dense square block(s) paired with SACC selectors for sacc_io.assemble_covariance, reusing statistics.cov_from_one_covariance for the per-block reshape (col 10 gaussian / col 9 gauss+non-gaussian). Single-block and multi-block (tomography-ready) forms. Tests (test_one_covariance_io.py, 9 passing): reshape to a hand-built matrix + gaussian/gauss+ng column selection + perturbation teeth; blocks feed assemble_covariance and round-trip s.covariance.dense; n(z) write/read round-trip, UNIONS dir_key, header/no-header, and fail-fast on mismatched grids / missing bin / bad value_loc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ather
Adversarial-review hardening (one HIGH, one MEDIUM, one coverage gap):
- HIGH: n_bins>1 silently truncated — n_bins drove only the NZDATA column
count while data/covariance were read from bin (0, 0), so a 2-bin SACC
emitted a plausible-looking FITS carrying 1/3 of the data. The converter
now fails fast unless n_bins == 1 and the ξ tracer pairs are exactly
{(source_0, source_0)}; tomographic emission lands with the tomographic
round.
- MEDIUM: a ξ-less SACC wrote an empty XI_PLUS and a (0, 0) COVMAT
silently; now a loud ValueError.
- Coverage: every prior covariance test exercised the identity permutation
(single-pair SACC order is already type-major). A (row, col)-encoded
covariance test now pins the exact np.ix_ gather of COVMAT (block-diag
ξ + joint non-adjacent [τ0+; τ2+]) and COVMAT_CELL — any transposition,
offset, or swapped block fails.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Ko89uZF84ez6HEDcTWbJe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #246. PR 3 of the PRD #241 series (row 3 of §7); stacked on #245 (
sacc_io).What
Adds the two converters that let SACC become the standard data-product format while the existing inference chain runs untouched behind it (PRD #241 §2):
sp_validation.twopoint_convert—sacc_to_twopoint_fits(s, path, *, rho_stats_hdu=None, tau_stats_hdu=None, n_bins=1): converts an analysis SACC into the CosmoSIS 2pt-FITS that2pt_like(and the ρ/τ2pt_like_xi_sysfork) reads, reproducing today'scosmo_inference/scripts/cosmosis_fitting.pyassembly HDU-for-HDU.sp_validation.one_covariance_io— the two pieces of SACC↔OneCovariance glue:write_nz/nz_table/nz_config_stanza/read_nz(SACCsource_in(z) → OneCovariance's combined n(z) text file +[redshift]config stanza), andcovariance_blocks(OneCovariance's flatcovariance_list_*.datoutput → dense covariance blocks paired with SACC selectors forsacc_io.assemble_covariance, reusingstatistics.cov_from_one_covariance).Purely additive: no existing file is modified.
Why
The converter is the bridge in the PRD's "converter first, native SACC likelihood later" plan: it lets PR 4 migrate the per-statistic writers to SACC without touching CosmoSIS, and the byte-compare against a current product is the validation the PRD calls for. The OneCovariance glue replaces the hand-rolled n(z)→config and covariance-reshaping we do today.
How it's built
[ξ+; ξ−]; the 2pt-FITS is type-major (all ξ+, then all ξ−). The data vector and its covariance are permuted vias.indices.n_bins != 1or any ξ tracer pair beyond(source_0, source_0)— no silent truncation. Tomographic emission lands with the tomographic round.[τ_0+; τ_2+]block, not block-diagonal —covdat_to_fitstruncates the 3-statistic CosmoCov τ covariance to 2 blocks and keeps the τ_0↔τ_2 cross-correlation. Pinned by a dedicated test.varrho_*variances the SACC layout does not store, so the converter copies RHO_STATS verbatim from the sidecar (never fabricates variances), exactly asrho_to_fitsdoes. This is the settled contract, not a stopgap: the PSF likelihood (cosmo_inference/scripts/xi_sys_psf.py:33-49) reads only the ρ_k± values — never the variances — so there is no consumer that would want the variances lifted into SACC. ξ±, Cℓ, n(z) and the covariance are fully rebuilt from SACC alone.__main__builds a CELL_BB HDU and discards it, appending CELL_EE alone; the converter matches. The SACC still carries EE/BB/EB with windows for the harmonic B-mode path.How it's validated
Byte equality against the current
cosmosis_fitting.py(astropy writes FITS deterministically), on both synthetic and real inputs.test_twopoint_convert.py(committed CI, 9 tests): build a reference with the current script's own HDU-builders on deterministic synthetic inputs, build a SACC from the same inputs, convert, and assert byte equality — for all three product shapes (plain-xi; xi+Cℓ; xi+ρ/τ). Plus the τ_0↔τ_2 cross-correlation, a perturbation teeth test, sidecar fail-fast, and the adversarial-review hardening below.test_twopoint_convert_realdata.py(candide-local,skipifon path existence, 4 tests): build a SACC from a real product's own contents, convert, byte-compare against the current writer. Observed byte-equal forSP_v1.4.6_leak_corrand aglass_mocksibling. The stale on-disk files differ only by an extra CELL_BB HDU (they predate its removal) and ~1e-17 float noise on n(z) bin edges — documented and guarded, no real data committed.test_one_covariance_io.py(9 tests): reshape to a hand-built matrix + gaussian/gauss+ng column selection + perturbation teeth; blocks feedassemble_covarianceand round-trips.covariance.dense; n(z) write/read round-trip, the UNIONSz_directorykey variant, and fail-fast on mismatched grids / missing bin / badvalue_loc.An independent adversarial review before opening found one HIGH (a tomographic SACC +
n_bins=2silently emitted a plausible-looking file carrying only the(0,0)data — now a loud error), one MEDIUM (ξ-less SACC wrote an empty product), and one coverage gap (every covariance test exercised the identity permutation; a (row,col)-encoded-covariance test now pins the exactnp.ix_gather so any transposition or block swap fails). All fixed in700a885.Full fast suite: 163 passed, 2 skipped, 2 failed — both failures pre-existing and environmental (
test_bmodes_workflow_dry_runsneeds snakemake in the local venv;test_configured_paths_exist_on_candidechecks data paths that resolve only from the main checkout), unrelated to this branch.Note on the on-disk references
The committed 2pt-FITS products on candide were written by an older
cosmosis_fitting.py(they carry a CELL_BB HDU and order COVMAT before NZ_SOURCE), so the byte-compare targets the current writer, which PR 4 will use to regenerate them. The direct diff against the on-disk files is verified to be exactly the CELL_BB addition, with every shared HDU matching to float precision.— Claude (Fable, with Opus implementation agents) on behalf of Cail.
🤖 Generated with Claude Code
https://claude.ai/code/session_016Ko89uZF84ez6HEDcTWbJe