theory_fn protocol, default CCL backend, pure order-independent shift draw#4
Draft
cailmdaley wants to merge 7 commits into
Draft
theory_fn protocol, default CCL backend, pure order-independent shift draw#4cailmdaley wants to merge 7 commits into
cailmdaley wants to merge 7 commits into
Conversation
Replace the firecrown-likelihood theory path with a single theory_fn(cosmo_params) -> np.ndarray protocol. ConcealDataVector now takes (fiducial_params, shifts_dict, sacc_data, *, seed, theory_fn=None, shift_distr): both theory vectors come from theory_fn (the shipped default CCL cosmic-shear backend when None, else the caller's), the concealed point is the fiducial mapping with drawn deltas overlaid, and the save path writes the blinded mean back through SACC's own API with the covariance carried over unchanged. - smokescreen/backends/ccl.py: default cosmic-shear theory_fn built from a SACC's n(z) tracers and cosmic-shear rows (Cl_ee, xi_plus/minus). pyccl is imported here, so `import smokescreen` imports no theory backend. - param_shifts.draw_param_shifts: pure, order-independent (sorted keys, one scalar draw per key) local-RNG draw returning deltas; seed int|str with SHA-256 string normalization; no global np.random.seed. - Drop _verify_sacc_consistency, _create_concealed_cosmo, systm_dict, save_to_sacc/get_sacc_indices, and the firecrown/ParamsMap imports. The sole construction guard is a theory-vs-mean length check. - utils: pyccl/sacc imports made lazy; remove firecrown-only helper. - __main__: CLI reworked onto the new signature + default backend. The firecrown cosmic-shear example likelihood is retained in examples/ as inherited-upstream, unsupported code; the package imports it nowhere. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
…odule Preserve upstream's firecrown-likelihood blinding class (pre-refactor ConcealDataVector) as FirecrownConcealDataVector in its own module, so the fork does not amputate the upstream firecrown integration a later DESC PR might restore. All firecrown and pyccl imports are function-local (via a _import_firecrown() helper and local imports), so importing this module — or importing smokescreen — imports no firecrown. It is not wired into the default flow (no main module imports it) and no fork test exercises it; the module docstring records it as inherited-upstream and unsupported here. The supported path remains smokescreen.datavector.ConcealDataVector. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
Mechanics tests (construction, draw, concealing factor, apply, save) now run against a synthetic theory_fn closure, importing neither pyccl nor firecrown. Adds the order-independence / delta / local-RNG / string-seed draw tests, subprocess import-discipline tests (pyccl and firecrown absent from sys.modules after a fresh `import smokescreen`; pyccl present only once the CCL backend is built), a small default-CCL-backend end-to-end test, and the length-guard test. CLI tests updated to the new datavector_main signature. Every firecrown/likelihood/_verify_sacc_consistency test and the mock-likelihood fixture are removed; no test depends on firecrown. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
…ventions Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
… list envelopes Each key now gets its own RNG derived from (seed, key), so the docstring contract — a delta depends only on (key, seed, shift_distr) — is actually true: adding or removing parameters from the shifts envelope no longer changes other parameters' hidden shifts. Golden-value tests pin the seed-normalization and both distributions cross-run/cross-machine; a subset-invariance test guards the per-key contract; gaussian tests now discriminate the distribution (differs from flat, escapes the flat bound). [lo, hi] lists (the natural YAML/JSON form) are accepted alongside tuples. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
…stody and the Cl branch Unknown shifts_dict keys now raise a clear ValueError instead of a bare KeyError; the length guard becomes a full shape check (via a shared _checked_theory_vec, also applied to the concealed-point evaluation), so an (n,1) theory_fn can no longer broadcast the blinded mean into an (n,n) matrix and silently corrupt the saved SACC. New tests: column-vector rejection, unknown-key rejection, seed-is-required TypeError, and cl_ee rows in the default-CCL-backend fixture so the np.interp Cl branch is exercised. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
assert_called_once_with(factor_type='add') instead of a bare call check, matching the shift_distr verification the gaussian variant already does. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
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.
End state
Blinding is driven by a single theory-function protocol instead of a firecrown likelihood.
ConcealDataVectorobtains both theory vectors (fiducial and hidden) by calling atheory_fn(cosmo_params) -> np.ndarray; the fork ships a default CCL cosmic-shear backend so a standard SACC blinds out of the box, and a caller can supply any callable.import smokescreenimports no theory backend —pycclenterssys.modulesonly when the default backend is constructed, and firecrown is never imported at module scope anywhere in the package.Closes #2
Interfaces
ConcealDataVector(fiducial_params, shifts_dict, sacc_data, *, seed, theory_fn=None, shift_distr="flat")fiducial_paramsis a plain mapping of cosmological-parameter name → value (CCL-native names); it replaces the oldcosmo+likelihoodpair. The hidden point isfiducial_paramswith the drawn deltas overlaid — nopyccl.Cosmologyobject, no_create_concealed_cosmo.theory_fn=Nonebuilds the default CCL backend fromsacc_data; supplying a callable overrides it. Nosystm_dict— systematics, if a backend needs them, are closed over inside itstheory_fn.seedis keyword-only with no default (blinding custody depends on a deliberate secret seed).intorstr; a string is normalized to an int via SHA-256.len(theory_fn(fiducial_params)) == len(sacc_data.mean)); the value/covariance_verify_sacc_consistencycheck is dropped, not re-expressed.calculate_concealing_factor("add"|"mult")computestheory_fn(concealed) - theory_fn(fiducial)(or the ratio);apply_concealing_to_likelihood_datavec()returnssacc_data.mean + factor(or* factor).save_concealed_datavectordeep-copies the SACC, overwrites its mean, carries the covariance over unchanged, stamps custody metadata + seed, and writes through SACC's ownsave_fits/save_hdf5— no firecrown, nosave_to_sacc/get_sacc_indices.draw_param_shifts(shifts_dict, seed, shift_distr="flat") -> dict[str, float](smokescreen.param_shifts)numpy.random.default_rng; never touches process-globalnp.random).float h→ symmetric envelope(-h, +h);(lo, hi)tuple → delta box."gaussian"accepts only thefloatform.intused as-is;strreduced to a 64-bit int via SHA-256 of its UTF-8 bytes (stable across runs/machines).Default CCL backend (
smokescreen.backends.ccl.build_ccl_theory_fn)import pycclin the package; imported when the backend is constructed. Given a SACC with weak-lensing n(z) tracers and cosmic-shear rows (galaxy_shear_cl_eeand/orgalaxy_shear_xi_plus/xi_minus), it builds aWeakLensingTracerper bin and returns the Cℓ / ξ± vector aligned tosacc_data.mean. Two documented conventions of this convenience backend (its row-to-theory contract): it defaults to CCL-nativeeisenstein_hu+halofitso it runs on a barepycclinstall with no Boltzmann code (overridable viacosmo_params), and it reads the ξ±thetatag as arcminutes (converted to degrees forpyccl.correlation).Inherited firecrown path (
smokescreen.firecrown_datavector.FirecrownConcealDataVector)examples/is likewise untouched.CLI (
smokescreen.__main__)datavectorreworked onto the new surface:datavector_main(path_to_sacc, fiducial_params, shifts_dict, seed, shift_type='add', shift_distribution='flat', path_to_output=None, keep_original_sacc=False, output_suffix=None), driving the default CCL backend (the firecrown-specificlikelihood_path/systematics/reference_cosmologyparams are gone).encrypt/decryptare unchanged.Test coverage
The suite runs firecrown-free (pyccl present) — 57 passed, nothing skipped for a missing firecrown.
theory_fnclosure (importing neither pyccl nor firecrown): construction, concealing factor equals the theory difference bit-for-bit for"add"and the ratio for"mult", apply returnsmean ± factor, save writes the blinded mean with the covariance untouched and the custody metadata stamped, and the length guard raises on a mismatch.(shifts_dict, seed)reproduces a fixed shift; permuting the key order yields identical per-key deltas; the draw leavesnp.random's global state untouched; the drawn value is a delta within the envelope (not an absolute); a string seed and its normalized int agree.import smokescreen(andimport smokescreen.datavector), neitherpycclnorfirecrownis insys.modules;pycclappears only once the CCL backend is built.Notes for review
_verify_sacc_consistencyis intentionally absent (row-to-theory alignment is the backend's contract; with no likelihood there is no second internal vector to compare against). This is a deliberate, non-behavior-preserving change.pyccldependency declaration, CI wiring, and install docs are out of scope here (separate packaging sub-PR);pyproject.toml, CI workflows, and README are untouched.🤖 Generated with Claude Code
https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf