Skip to content

PSF leakage: joint errors-in-variables ρ/τ fit by default - #454

Open
cailmdaley wants to merge 18 commits into
developfrom
feat/leakage-eiv-estimator
Open

cailmdaley wants to merge 18 commits into
developfrom
feat/leakage-eiv-estimator

Conversation

@cailmdaley

@cailmdaley cailmdaley commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Claude (Opus) on behalf of Cail.

Where this fits. On the full UNIONS v2 area the ρ/τ PSF-leakage fit fails, with χ² 171/57. #452 diagnoses three causes:

Checking this PR against a known answer on mocks exposed a fourth problem: the template the fit uses for α doesn't match how leakage enters the galaxies. That is fixed upstream in CosmoStat/shear_psf_leakage#59 (closing #58 and #52) and adopted here.

Why change the estimator

The default lsq fit takes the measured ρ as exact and ignores the ρ–τ cross-covariance. At small θ, the noise in ρ propagated through the model is 100–500× the τ variance. So lsq's χ² and errors are wrong exactly where the fit has most weight. A joint errors-in-variables (EIV) fit handles this: it fits the true ρ alongside (α, β, η), under one jackknife covariance of ρ and τ together. #452 showed the cross-covariance term matters: dropping it fakes a pass, 69/57 instead of 78/57.

Why change α's template

The leakage model is e_gal += α·p_gal + β·(PSF error) + η·(size term), with τ the correlations of galaxy ellipticity with the star fields. The α column of the fit has been ρ, the PSF at stars, uncentred. Two things make that wrong:

  • Centring: τ is built from galaxy ellipticities with their weighted mean removed, which also removes α times the mean PSF at the galaxies. ρ keeps its mean.
  • Sampling: the leakage acts through the PSF at galaxy positions, not at stars.

α's column is now the PSF at galaxy positions, centred on the selected galaxies' weighted mean, correlated with the same star fields as τ. Its jackknife rows replace the old ones inside the joint covariance. ρ itself is unchanged, since it still feeds β, η and ξ_sys.

Known answer. We used two GLASS mocks painted on the real v2 catalogue that differ only by e += 0.1·p_gal:

α template Δα (truth 0.1)
ρ at stars, uncentred (previous default) 0.080 ± 0.007
ρ at stars, centred 0.126 ± 0.007
centred PSF at galaxies (this PR) 0.0999999998

Through this PR's own measurement and fit, the full twin gives Δ(α, β, η) = (0.0999999998, −8×10⁻⁹, −2×10⁻⁸). Δτ matches 0.1 × the new α column to 10⁻¹³, in the full-sample vector and in every 200/400/800-patch jackknife row. The exact recovery is a consistency check: the twin difference is α times the centred galaxy PSF, so this shows the statistics and the fit now agree with the model; it doesn't test whether real leakage has that form. Each catalogue's own σ_α is 0.0053.

Δα, Δβ, Δη per α template on the GLASS twin; bottom: the centring and sampling parts of Δτ − 0.1ρ

Not yet measured: the corrected fit on real v2 data. From the mock, the old template biased α low by about 20–25%, which is about 0.005 at α ≈ 0.02, below σ_α but systematic.

What changes

  • rho_tau_method: eiv is the default.
    • Measurement: one TreeCorr pass measures ρ0–ρ5, τ0/τ2/τ5 and the α template on the same 800 star-derived patch centres.
    • Covariance: delete-one jackknife rows over all of them together. The 200- and 400-patch versions merge neighbouring patches (Ward clustering) without recounting pairs; 400 is the fiducial.
    • Fit: the noisy predictors are profiled out of a Hartlap-scaled χ² with the full predictor–τ cross-covariance.
    • Outputs: downstream code still receives Gaussian (α, β, η) samples. lsq and emcee remain selectable.
  • β(T_PSF) = β₀ + β₁(T_PSF/⟨T_PSF⟩ − 1) is an option, off by default (psf_leakage.beta_psf_size). Its template is carried through the fit and ξ_sys.
  • Caches. The rule cv_leakage_jackknife measures the joint products, and fitting and plotting read them. Every cached τ and leakage product records its field definition, columns, responses and selection, so a product made with the old full-catalogue centring can't be reused silently.
  • Dependency. shear_psf_leakage is pinned to Cosmo val lisa #59's head (d0e10d83). It moves to the merge commit once Cosmo val lisa #59 merges.

Validation

Limits.

Refs #452

🤖 Generated with Claude Code

https://claude.ai/code/session_01JK7o9EG5R1yAPT98V9j2GJ

Cail Daley and others added 13 commits October 30, 2026 12:42
…ky mask

Pure-numerics module for the PSF-leakage fit: the rho->tau design, the
k-template joint EIV profile fit (residual covariance from joint delete-one
rows including the rho-tau cross term, Hartlap-scaled chi2, profile-Hessian
errors), Ward grouping of fine patches, O(pairs) TreeCorr match-jackknife
rows with optional grouping, the circle sky mask, and xi_sys = a^T M b.
Reproduces the leakadq reference fits on its bound9clean rows to 1e-12 in chi2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
measure_leakage_jackknife builds stars and galaxies as get_rho_tau does,
with npatch_fine shared k-means centres, and in one pass of match-weighted
GG correlations measures rho0..rho5, tau0/2/5 and optionally the u*de
PSF-size templates; delete-one rows at the fine count and at Ward unions
for each patch count come from the per-patch-pair results. Products are
cached as npz + json keyed by the measurement settings. fit_leakage and
get_samples_eiv run the joint EIV fit and draw Gaussian samples.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rho_tau_method 'eiv' (now the default) fits the joint rho/tau jackknife
measurement and reports alpha, beta, eta with covariance, chi2/dof and PTE
at each psf_leakage patch count, drawing downstream samples from the
fiducial fit. psf_leakage settings: npatch_fine 800, patch_counts
[200, 400], fiducial_npatch 400, beta_psf_size false, and the sky mask
config/masks/star_contamination.json (M33, M101, M13, M92), applied to
stars and galaxies in every rho/tau measurement. With beta_psf_size,
xi_sys includes the u*de terms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cosmo_val config selects rho_tau_method eiv with the psf_leakage
settings, forwarded to every cosmo_val rule and to rho_tau_stats for the
sky mask. cv_rho_tau_fits depends on the joint measurement under eiv and
stores the per-patch-count fit summary in the PSF product.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bound-9 measurement (170M galaxies, 800 patches, slope templates)
peaked at 83 GiB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A cached rho_stats/tau_stats file made before the sky mask (or with any
other selection) no longer satisfies measurement_matches; the metadata
records a digest of the row masks it was measured on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9EfMQEn7kKMQzWV5o2
…stable

The best trial is the lowest objective among the BFGS runs that converged
(bfgs_success False when none did); sigma and the parameter covariance are
None when the profile Hessian is not positive definite (Cholesky test).
residual_covariance_model exposes V(p) and dV/dp, checked against L C L^T
of an explicit joint jackknife covariance with a template column, and the
noisy fit against a direct minimisation of the dense chi2. The design and
constant-beta xi_sys are checked against PSFErrorFit. Unused returns
(jackknife weights, residual covariance) are dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9EfMQEn7kKMQzWV5o2
leakage_jackknife measures only with measure=True, which the rule
cv_leakage_jackknife passes; the fits, get_samples, xi_psf_sys and
interactive use read the cache and raise, naming the rule, when it is
missing or stale. The cache key records the star and star+galaxy
selection digests and leaves out cross_patch_weight, which the
measurement overrides. The fit summary JSON carries the Hartlap factor,
BFGS success, gradient norm and the profile Hessian's positivity and
eigenvalues; get_samples_eiv raises when the fiducial Hessian is not
positive definite. Tomographic bins draw samples from seeds derived from
the bin id. The u de template must have the de catalogue's rows (and
weights). The docstring says where galaxy ellipticities are centred.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9EfMQEn7kKMQzWV5o2
Every patch count must lie strictly between 1 and npatch_fine, and the
fiducial count must be one of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9EfMQEn7kKMQzWV5o2
get_theory_cov records the star/galaxy selection_digest beside
cov_tau_*_th.npy and reuses it only for the same selection. The lsq and
emcee sample caches carry the selection recorded beside the tau statistics
in their names, so remeasured statistics on other rows are refitted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9EfMQEn7kKMQzWV5o2
With beta_psf_size the samples are (alpha, beta0, eta, beta1): the getdist
contours (cosmo_val and the cv_plot_rho_tau_fits renderer) and the
dashboard's coefficient draws take names, labels and markers from the
sample width, and the dashboard tau model adds beta1 times the
<u de, {p, de, q}> template, which cv_rho_tau_fits now stores as
tau_slope_template (it raises without it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9EfMQEn7kKMQzWV5o2
rho_tau_stats and cv_leakage_jackknife list the psf_leakage sky-mask JSON
as input, so editing its circles reruns them, and rho_tau_stats receives
only the sky-mask setting rather than the whole psf_leakage dict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9EfMQEn7kKMQzWV5o2
…mask

cv_leakage_jackknife lists each version's PSF catalogue and the rho/tau
rules the sky-mask file as inputs; the toy catalogue config had no psf
block and the toy checkout no config/masks, so every DAG test failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9EfMQEn7kKMQzWV5o2
Masking of contaminated PSF stars belongs upstream in ShapePipe, so the
rho/tau measurements here use only the star (HSM flags) and galaxy
(tomographic bin) selections. Removes config/masks/star_contamination.json,
the psf_leakage sky_mask setting, leakage_fit.keep_sky, the workflow
sky-mask inputs and params, and the toy checkout's mask copy. The
selection-keyed caching of rho/tau products stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7o9H5tLNFzcwRnYwMFEA
@cailmdaley cailmdaley changed the title PSF leakage: joint errors-in-variables ρ/τ fit and star-contamination mask by default PSF leakage: joint errors-in-variables ρ/τ fit by default Oct 30, 2026
…stimator

# Conflicts:
#	src/sp_validation/rho_tau.py

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant