clenspy.kernels.lensing_kernel.LensingKernel¶
- class clenspy.kernels.lensing_kernel.LensingKernel(survey, cosmology, unity=False)[source]¶
Bases:
objectSource-averaged \(\Sigma_{\rm crit}\) weights for one survey.
NOTE: units and conventions are the module’s – comoving \(\Sigma_{\rm crit}\), h-free, Msun/Mpc^2.
NOTE: the constructor stores and computes nothing. The interpolant over \(z_l\) is built on first use of kernel_z, so constructing this object is free.
- Parameters:
survey (object) – Anything satisfying the ~clenspy.protocols.Survey protocol – clenspy.survey.Survey in practice. Stored verbatim.
cosmology (astropy.cosmology.Cosmology) – The world model. Stored verbatim.
unity (bool, optional) –
If True, mean_inverse_sigma_crit returns 1 everywhere, so every downstream consumer emits \(\Delta\Sigma\) instead of \(\gamma_t\) (default: False).
NOTE: this is the clean protocol seam, and it is what the y3 pipeline’s
unity=Toption does – it is how a \(\Delta\Sigma\) data vector is compared against a model written for shear, with no second code path.
Methods
__init__(survey, cosmology[, unity])f_src_behind(z_halo[, min_separation, n_nodes])Fraction of sources behind \(z_h\), dimensionless.
kernel_z(z_lens[, delta_z])mean_inverse_sigma_crit, interpolated over \(z_l\).
mean_inverse_sigma_crit(z_lens[, delta_z])\(\langle\Sigma_{\rm crit}^{-1}\rangle(z_l)\) [Mpc^2/Msun].
mean_sigma_crit(z_halo[, min_separation, ...])\(\langle\Sigma_{\rm crit}\rangle(z_h)\) [Msun/Mpc^2 comoving].
q_sigma(z_lens, z_halo[, min_separation, ...])The \(\Sigma_{\rm crit}\)-weighted kernel \(q_\Sigma(z_l; z_h)\).
- mean_inverse_sigma_crit(z_lens, delta_z=0.0)[source]¶
\(\langle\Sigma_{\rm crit}^{-1}\rangle(z_l)\) [Mpc^2/Msun].
\[\langle\Sigma_{\rm crit}^{-1}\rangle(z_l) = \int\! dz_s\; p(z_s + \Delta z)\, \max\!\left[0,\, \Sigma_{\rm crit}^{-1}(z_l, z_s)\right]\]The inverse is averaged, which is not the inverse of mean_sigma_crit and differs from it by the source weighting.
- Parameters:
- Returns:
np.ndarray – The average, or ones if
unity– see the class NOTE.
- kernel_z(z_lens, delta_z=0.0)[source]¶
mean_inverse_sigma_crit, interpolated over \(z_l\).
Same quantity, evaluated on a _N_ZL_NODES grid once and interpolated after – which is what a Limber integral over \(\chi\) wants, since it evaluates the kernel at every node.
NOTE: the grid spans \([z_s^{\min}, z_s^{\max}]\), and the interpolant is not extrapolated: outside it the result is zero, because a lens behind every source is unlensed.
NOTE: cached on the instance keyed by
delta_z, so sweeping a photo-z bias does not silently reuse the wrong grid.- Parameters:
delta_z (float)
- q_sigma(z_lens, z_halo, min_separation=None, n_nodes=None)[source]¶
The \(\Sigma_{\rm crit}\)-weighted kernel \(q_\Sigma(z_l; z_h)\).
\[q_\Sigma(z_l; z_h) = \int\! dz_s\; p(z_s)\, \frac{\Sigma_{\rm crit}(z_h, z_s)} {\Sigma_{\rm crit}(z_l, z_s)}\]NOTE: cutoff-defined. The integrand diverges as \(z_s \to z_h\), so the value depends on
min_separation(floored at MIN_LENS_SOURCE_SEPARATION) and, through the endpoint’s trapezoid weight, onn_nodes. Both default to the values the frozen covariance reference was built with. The frozen reference is itself signed: for \(z_s\) between \(z_l\) and \(z_h\) the ratio changes sign, and itsq_sigmaruns from -2.29 to +3.91. That is the definition, not a bug – do not clamp it.Dimensionless. It is the weight with which structure at \(z_l\) contributes to a \(\Sigma\) measured around a halo at \(z_h\) – the ratio, not either factor alone, which is why the \(c^2/4\pi G\) cancels and only geometry survives.
NOTE: the source range starts at \(z_l\) +
min_separation, keyed on the lens, not on the halo. So when \(z_l < z_h\) the range includes sources in front of the halo, where \(\chi_s - \chi_h < 0\) and \(\Sigma_{\rm crit}(z_h, z_s)\) is negative. The frozen reference keeps that sign – itsq_sigmaruns from -2.29 to +3.91 – so this is the definition and the integrand is not clamped. Clamping it, or keying the range on \(\max(z_l, z_h)\), changes the covariance.NOTE: the same range choice puts the \(z_s = z_h\) pole inside the integral whenever \(z_l < z_h\). The trapezoid straddles it and returns a finite but grid-dependent number, which is where the \(\pm 4\) excursions come from. That is inherited from the reference definition, not introduced here.
NOTE: measured consequence: for \(z_l < z_h\) the value does not converge in
n_nodes(z_h = 0.425, z_l = 0.153: -0.03, 0.44, 1.24, 0.68 at 100, 200, 400, 3200 nodes), and \(C_\ell^{\Sigma\Sigma}\) built from it changes by O(1) with the slab width. Restricting sources to \(z_s > z_h\) removes both; which restriction is intended is an open decision, seevalidation/covariance_review_REPORT.mdandvalidation/diagnose_qsigma_pole.py. Default unchanged.- Parameters:
z_lens (float or array-like) – Redshift of the lensing structure.
z_halo (float) – Redshift of the halo the profile is measured around.
min_separation (float, int, optional) – The two conventions the value depends on; see MIN_LENS_SOURCE_SEPARATION.
n_nodes (float, int, optional) – The two conventions the value depends on; see MIN_LENS_SOURCE_SEPARATION.
- mean_sigma_crit(z_halo, min_separation=None, n_nodes=None)[source]¶
\(\langle\Sigma_{\rm crit}\rangle(z_h)\) [Msun/Mpc^2 comoving].
\[\langle\Sigma_{\rm crit}\rangle(z_h) = \int_{z_h}\! dz_s\; p(z_s)\,\Sigma_{\rm crit}(z_h, z_s)\]NOTE: cutoff-defined. Sources just behind the lens have unbounded \(\Sigma_{\rm crit}\), so without a floor the average does not exist; this returns the integral from \(z_h + \delta\), with \(\delta\) =
min_separation(MIN_LENS_SOURCE_SEPARATION, 0.01, by default). For a given \(\delta\) it converges under Gauss-Legendre (96 nodes: 3e-11 even at 0.01); an earlier note here said refining the grid lowered the answer, but that was the trapezoid’s first interval, not the physics. The value does depend on \(\delta\) – 0.1 versus 0.01 changes it by up to a factor 5 – which is why the covariance pins it.NOTE: not the reciprocal of mean_inverse_sigma_crit. Both are needed and they are different averages; see errata E.1 item 1. That one is convergent, which is the deeper reason to prefer it.
NOTE: not normalised by f_src_behind: the integral over the whole source distribution, with sources in front contributing zero, so it carries the behind-fraction implicitly. The covariance shape noise does not use this directly any more: since
cluster-lensing-covcddbb2a it uses the conditional average over lensed sources,mean_sigma_crit(z, 0.1) / f_src_behind(z, 0.1)(cut MIN_LENS_SOURCE_SEPARATION_NOISE), which LimberProjector.shape_noise_Sigma forms from this method.
- f_src_behind(z_halo, min_separation=None, n_nodes=None)[source]¶
Fraction of sources behind \(z_h\), dimensionless.
\[f_{\rm src}(z_h) = \int_{z_h + \delta}^{z_s^{\max}}\! dz_s\; p(z_s)\]Falls to zero at the top of the source distribution and is 1 below its bottom, since \(p(z_s)\) is normalised.
- Parameters:
z_halo (float or array-like) – Lens redshift(s).
min_separation (float, optional) – The cut \(\delta\) (default MIN_LENS_SOURCE_SEPARATION, 0.01). The covariance shape noise passes MIN_LENS_SOURCE_SEPARATION_NOISE (0.1), as
cluster-lensing-covcddbb2a does.n_nodes (int, optional) – Gauss-Legendre order (default N_ZS_GL).