lenspyx.wigners
Wigner small-d functions and correlation functions for spin-weighted spherical harmonics.
This module provides efficient implementations of Wigner small-d functions and their associated correlation functions, which are fundamental for analyzing spin-weighted fields on the sphere (e.g., CMB polarization, gravitational lensing).
Overview
Wigner small-d functions \(d^\ell_{s_1 s_2}(\theta)\) are the angular parts of the Wigner D-matrices, describing the rotation of spin-weighted spherical harmonics. They appear in:
Correlation functions of spin-weighted fields (e.g., ξ± for CMB polarization or galaxy surveys)
Angular power spectrum estimators for CMB polarization
Lensing reconstruction and delensing operations
General spin transformations on the sphere
API Reference
Forward Transforms
- lenspyx.wigners.wignerpos(cl: ndarray[float], theta: ndarray[float], s1: int, s2: int)[source]
Produces Wigner small-d transform defined by
\[\sum_\ell \frac{2\ell + 1}{4\pi} C_\ell d^\ell_{s_1 s_2}(\theta)\]- Parameters:
cl (array_like) – Spectrum of Wigner small-d transform (power spectrum \(C_\ell\))
theta (array_like) – Co-latitude in radians (in [0, π])
s1 (int) – First spin weight
s2 (int) – Second spin weight
- Returns:
Real array of same size as theta containing the correlation function
- Return type:
array_like
Notes
You can use
wigner4pos()instead if you also need the result for -s2 (e.g., for computing \(\xi_{\pm}\) simultaneously).See also
wigner4posCompute 4 correlation functions in one go
wignercoeffAdjoint transform (correlation function to spectrum)
- lenspyx.wigners.wigner4pos(gl: ndarray[float], cl: ndarray[float], theta: ndarray[float], s1: int, s2: int)[source]
Compute 4 Wigner correlation functions in one go.
- Parameters:
gl (array_like) – First spectrum (power spectrum \(g_\ell\))
cl (array_like or None) – Second spectrum (power spectrum \(c_\ell\)). Can be set to None if irrelevant, and is ignored if s2 is zero.
theta (array_like) – Co-latitude in radians (in [0, π])
s1 (int) – First spin weight
s2 (int) – Second spin weight
- Returns:
In the most general case, an array of shape (ncomp, ntheta) with:
Component 0: \(\sum_\ell g_\ell \frac{2\ell + 1}{4\pi} d^\ell_{s_1, |s_2|}(\theta)\)
Component 1: \(\sum_\ell g_\ell \frac{2\ell + 1}{4\pi} d^\ell_{s_1,-|s_2|}(\theta)\)
Component 2: \(\sum_\ell c_\ell \frac{2\ell + 1}{4\pi} d^\ell_{s_1, |s_2|}(\theta)\) (if cl is not None)
Component 3: \(\sum_\ell c_\ell \frac{2\ell + 1}{4\pi} d^\ell_{s_1,-|s_2|}(\theta)\) (if cl is not None)
The number of components ncomp in the output is:
4 if (s2 ≠ 0 and cl is not None)
2 if (s2 ≠ 0 and cl is None)
1 if s2 = 0
- Return type:
array_like
Notes
This function is more efficient than calling
wignerpos()multiple times when you need correlation functions for both +s2 and -s2 (e.g., ξ+ and ξ-).See also
wignerposCompute single correlation function
Adjoint Transforms
- lenspyx.wigners.wignercoeff(xi: ndarray[float], theta: ndarray[float], s1: int, s2: int, lmax: int)[source]
Computes spectrum of Wigner small-d correlation function (adjoint to wignerpos).
This is the adjoint transform that converts a correlation function to its power spectrum:
\[C_\ell = 2\pi \sum_\theta \xi(\theta) d^\ell_{s_1 s_2}(\theta)\]- Parameters:
xi (array_like) – Wigner correlation function (real array, one value per co-latitude)
theta (array_like) – Co-latitude in radians (in [0, π])
s1 (int) – First spin weight
s2 (int) – Second spin weight
lmax (int) – Maximum multipole (inclusive). Spectrum is calculated from 0 to lmax.
- Returns:
Power spectrum \(C_\ell\) from ℓ=0 to ℓ=lmax
- Return type:
array_like
Notes
This function implements the adjoint operation to
wignerpos(). It is used to estimate power spectra from measured correlation functions.See also
wignerposForward transform (spectrum to correlation function)
Convolutions
- lenspyx.wigners.wignerc(cl1: ndarray[float], cl2: ndarray[float], s1: int, t1: int, s2: int, t2: int, lmax_out: int = -1)[source]
Convolution of two Wigner small-d correlation functions.
Computes the power spectrum of the product of two correlation functions:
\[\xi_{s_1 t_1}(\mu) \times \xi_{s_2 t_2}(\mu)\]where
\[\xi_{s_1 t_1}(\mu) = \sum_{\ell} C_{1,\ell} \frac{2\ell + 1}{4\pi} d^\ell_{s_1 t_1}(\mu)\]\[\xi_{s_2 t_2}(\mu) = \sum_{\ell} C_{2,\ell} \frac{2\ell + 1}{4\pi} d^\ell_{s_2 t_2}(\mu)\]Gauss-Legendre quadrature is used to solve this exactly (up to numerical precision).
- Parameters:
cl1 (array_like) – Spectrum of first Wigner small-d function (\(C_{1,\ell}\))
cl2 (array_like) – Spectrum of second Wigner small-d function (\(C_{2,\ell}\))
s1 (int) – First spin of first function
t1 (int) – Second spin of first function
s2 (int) – First spin of second function
t2 (int) – Second spin of second function
lmax_out (int, optional) – Maximum multipole of output spectrum. Defaults to len(cl1) + len(cl2) - 2.
- Returns:
Power spectrum of the product correlation function, from ℓ=0 to ℓ=lmax_out
- Return type:
array_like
Notes
This function is useful for computing non-Gaussian covariances and higher-order statistics. The output has spins (s1+s2, t1+t2).
Wigner d-functions
- lenspyx.wigners.wignerd(l: int, s1: int, s2: int, theta: ndarray)[source]
Returns Wigner small-d functions for a specific multipole.
Computes the normalized Wigner d-functions:
\[\frac{2\ell + 1}{4\pi} d^\ell_{s_1, |s_2|}(\theta)\]and
\[\frac{2\ell + 1}{4\pi} d^\ell_{s_1,-|s_2|}(\theta)\]for all θ. If s2 is zero, only the first component is returned.
- Parameters:
l (int) – Multipole moment
s1 (int) – First spin weight
s2 (int) – Second spin weight
theta (array_like) – Co-latitude angles in radians
- Returns:
Array of shape (2, ntheta) if s2 ≠ 0, or (1, ntheta) if s2 = 0
- Return type:
array_like
See also
wignerdlReturns d^l_{s1,s2}(θ) without normalization for all ℓ
- lenspyx.wigners.wignerdl(s1: int, s2: int, theta: float, lmax: int)[source]
Returns the Wigner d-function for all multipoles.
Computes the Wigner d-function:
\[d^\ell_{s_1 s_2}(\theta)\]for all ℓ from 0 to lmax.
- Parameters:
s1 (int) – First spin weight
s2 (int) – Second spin weight
theta (float) – Co-latitude angle in radians (scalar)
lmax (int) – Maximum multipole moment
- Returns:
Array of size lmax+1 containing \(d^\ell_{s_1 s_2}(\theta)\) for ℓ=0 to lmax
- Return type:
array_like
Notes
This returns the unnormalized Wigner d-function, without the (2ℓ+1)/(4π) factor. For the normalized version, use
wignerd().See also
wignerdNormalized Wigner d-function for a specific ℓ
Quadrature Utilities
- lenspyx.wigners.get_thgwg(npts: int)[source]
Gauss-Legendre integration points and weights from DUCC0.
Provides quadrature points and weights for integration over the interval [0, π], optimized for integrating functions on the sphere.
- Parameters:
npts (int) – Number of quadrature points
- Returns:
tht (array_like) – Co-latitude points in radians (array of size npts)
wg (array_like) – Quadrature weights (array of size npts)
Notes
This uses DUCC0’s highly optimized Gauss-Legendre quadrature implementation. For a band-limited function up to ℓ_max, use npts ≥ (ℓ_max + 2) / 2 for exact integration.
Examples
>>> from lenspyx.wigners import get_thgwg >>> theta, weights = get_thgwg(100) >>> # Integrate a function f(θ) over the sphere: >>> integral = np.sum(f(theta) * weights)
- lenspyx.wigners.get_xgwg(a: float, b: float, npts: int)[source]
Gauss-Legendre points and weights for integration over an arbitrary interval.
Provides quadrature points and weights for integration over the interval [a, b].
- Parameters:
a (float) – Lower bound of integration interval
b (float) – Upper bound of integration interval
npts (int) – Number of quadrature points
- Returns:
xg (array_like) – Quadrature points within (a, b) (array of size npts)
wg (array_like) – Quadrature weights (array of size npts)
Notes
This function transforms the standard Gauss-Legendre quadrature on [-1, 1] to an arbitrary interval [a, b].
Examples
>>> from lenspyx.wigners import get_xgwg >>> x, weights = get_xgwg(0, 10, 50) >>> # Integrate a function f(x) over [0, 10]: >>> integral = np.sum(f(x) * weights)
Examples
Computing CMB E-mode correlation function
import numpy as np
from lenspyx.wigners import wignerpos
# E-mode power spectrum
cl_ee = np.loadtxt('cl_ee.txt')
theta = np.linspace(0, np.pi, 100)
# Compute ξ_EE(θ) = Σ_ℓ (2ℓ+1)/(4π) C_ℓ^EE d^ℓ_{2,2}(θ)
xi_ee = wignerpos(cl_ee, theta, s1=2, s2=2)
Computing ξ± correlation functions
from lenspyx.wigners import wigner4pos
# Returns [ξ+, ξ-] where:
# ξ+ = Σ_ℓ (2ℓ+1)/(4π) C_ℓ d^ℓ_{2,+2}(θ)
# ξ- = Σ_ℓ (2ℓ+1)/(4π) C_ℓ d^ℓ_{2,-2}(θ)
xi_plus, xi_minus = wigner4pos(cl_ee, None, theta, s1=2, s2=2)
Inverting correlation function to power spectrum
from lenspyx.wigners import wignercoeff, get_thgwg
lmax = 2000
npts = (lmax + 2) // 2
theta, weights = get_thgwg(npts)
# Measure ξ(θ) from data
xi_measured = measure_correlation(theta)
# Compute C_ℓ = 2π Σ_θ ξ(θ) d^ℓ_{s1,s2}(θ)
cl_recovered = wignercoeff(xi_measured, theta, s1=2, s2=2, lmax=lmax)
Convolving correlation functions
from lenspyx.wigners import wignerc
cl1 = cl_ee # E-mode spectrum
cl2 = cl_bb # B-mode spectrum
# Compute spectrum of ξ_EE(θ) * ξ_BB(θ)
cl_product = wignerc(cl1, cl2, s1=2, t1=2, s2=2, t2=2)
Notes
Spin values s1, s2 can be positive, negative, or zero
The normalization includes (2ℓ+1)/(4π) factors
Gauss-Legendre quadrature ensures exact integration for band-limited functions
The implementation uses DUCC0’s alm2leg and leg2alm functions, which achieve
excellent performance through compiler optimization.