A Python implementation of LU nulling for weak gravitational lensing tomography, following the methodology described in Huterer & White (2005).
LU nulling is a technique for removing systematic effects in weak lensing measurements by constructing linear combinations of tomographic bins that null specific redshift-dependent systematics while preserving cosmological signal. This package provides tools for:
- Computing Limber integrals for angular power spectra
- Performing LU decomposition of the Limber matrix
- Constructing nulling transformations with specified k-space cutoffs
- Multiple integration node sampling strategies (linear, adaptive quadrature, Monte Carlo)
This package requires Python 3.8+ and depends on:
- pyCCL - Core Cosmology Library
- NumPy
- SciPy
Install pyCCL via pip:
pip install pycclOr via conda:
conda install -c conda-forge pycclClone this repository and install in development mode:
git clone https://github.com/ahallcosmo/lunul.git
cd lunul
pip install -e .import lunul
import pyccl as ccl
import numpy as np
# Set up cosmology
cosmo = ccl.Cosmology(Omega_c=0.27, Omega_b=0.045, h=0.67, sigma8=0.8, n_s=0.96)
# Define redshift bins and create tracers
z_edges = np.array([0.2, 0.6, 1.0, 1.4, 2.0])
z_grid = np.linspace(z_edges[0], z_edges[-1], 200)
tracers = []
for i in range(len(z_edges)-1):
z_min, z_max = z_edges[i], z_edges[i+1]
# Create top-hat n(z) distribution for each bin
nz = np.where((z_grid >= z_min) & (z_grid <= z_max), 1.0, 0.0)
tracer = ccl.WeakLensingTracer(cosmo, dndz=(z_grid, nz))
tracers.append(tracer)
# Create nodes for integration
limits = lunul.get_global_lklimits(cosmo, tracers, ell=100)
nodes = lunul.LinearNodes(npoints=50, limits=limits)
# Perform LU nulling analysis
trimmer = lunul.Trimmer(cosmo, nodes, tracers, ell=100, kmax=10.0, tol=0.01)get_global_lklimits(cosmo, tracers, ell)- Compute global ln(k) limitsget_limber_matrix(cosmo, nodes, binpairs, ell)- Build Limber matrixcl_integrand(lk, cosmo, tr1, tr2, psp, ell)- Limber integrand
LinearNodes- Linearly spaced integration pointsQuadNodes- Adaptive quadrature-based samplingMCNodes- Monte Carlo sampling from integrand
Trimmer- LU decomposition and mode selection
For detailed API documentation, see the docstrings in the source code.
See the examples/ directory for Jupyter notebooks demonstrating:
- Basic LU nulling workflow
- Comparison of integration strategies
- Systematic removal validation
If you use this software, please cite:
Primary Reference:
@article{HutererWhite2005,
title={Nulling Tomography with Weak Gravitational Lensing},
author={Huterer, Dragan and White, Martin},
journal={Physical Review D},
volume={72},
number={4},
pages={043002},
year={2005},
publisher={APS}
}This Implementation:
@misc{RobertsonHall2025,
title={lunul: A Python implementation of LU nulling for weak lensing},
author={Robertson, N. and Hall, A.},
year={2025},
url={https://github.com/ahallcosmo/lunul}
}Core Cosmology Library: Please also cite the Core Cosmology Library (CCL) papers.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
- The DESC Core Cosmology Library
- The original LU nulling methodology by Huterer & White (2005)