CLensPy logo

CLensPy

Documentation Status License: MIT GitHub tag GitHub issues GitHub stars

Welcome to CLensPy, a Python package for cluster gravitational lensing analysis.

Overview

CLensPy provides a toolkit for computing weak-lensing observables from dark matter halo profiles: NFW and Einasto density profiles, projected surface density Sigma(R), excess surface density DeltaSigma(R), halo bias, and the two-halo term. It is designed to be:

  • Modular: each halo profile is a small, self-contained class with the same density / sigma / deltasigma interface

  • Fast: vectorized NumPy/SciPy implementations, with closed-form or series expansions used where available (e.g. the Einasto profile’s projected density)

  • Validated: cross-checked against independent codes (pyccl, cluster_toolkit, CLMM) in the test suite

Installation

CLensPy is not yet published on PyPI; install it from source:

git clone https://github.com/estevesjh/clenspy.git
cd clenspy
pip install -e .

See Installation for optional dependency groups (docs, compare, dev).

Quick Start

from clenspy.halo import EinastoProfile, NfwProfile

# h-free absolute units: mass in Msun, lengths in Mpc, densities in
# Msun/Mpc^3, wavenumbers in 1/Mpc -- no cosmology object needed, only the
# reference density rho_ref that mass_def is measured against (default:
# the comoving mean matter density, giving M_200m).
m200 = 1e14  # Msun
c200 = 5.0
nfw = NfwProfile(m200=m200, c200=c200)
print(f"r200 = {nfw.r200:.4f} Mpc, rs = {nfw.rs:.4f} Mpc, "
      f"rho_s = {nfw.rho_s:.3e} Msun/Mpc^3")

r = np.array([0.1, 0.5, 1.0, 2.0])  # Mpc
print("rho_NFW(r)     [Msun/Mpc^3] =", nfw.density(r))

# same r_s as the NFW halo (r_s = r200/c200), rho_0 solved so the enclosed
# mass at r200 matches m200 -- a fair shape-only comparison at fixed mass
# and scale radius. alpha=0.25 is a typical cluster shape (Retana-Montenegro
# et al. 2012 report alpha ~ 0.16-0.25 for clusters).
alpha = 0.25
rho0_unit = EinastoProfile(alpha=alpha, rho_0=1.0, r_s=nfw.rs, tol=1e-4)
rho0 = m200 / rho0_unit.enclosed_mass(nfw.r200)
einasto = EinastoProfile(alpha=alpha, rho_0=rho0, r_s=nfw.rs, tol=1e-4)
print("rho_Einasto(r) [Msun/Mpc^3] =", einasto.density(r))

# fourier() returns rho_tilde(k), the *unnormalized* FT -- units of mass,
# going to M as k -> 0, not the dimensionless mass-normalized u(k|M).
k = np.array([0.1, 1.0, 10.0])  # 1/Mpc
print("rho_tilde_NFW(k)     [Msun] =", nfw.fourier(k))
print("rho_tilde_Einasto(k) [Msun] =", einasto.fourier(k))

r200 = 1.4303 Mpc, rs = 0.2861 Mpc, rho_s = 3.547e+14 Msun/Mpc^3
rho_NFW(r)     [Msun/Mpc^3] = [5.57109391e+14 2.68756655e+13 5.02012592e+12 7.94381981e+11]
rho_Einasto(r) [Msun/Mpc^3] = [5.83600877e+14 2.77183496e+13 4.86300049e+12 6.13799586e+11]
rho_tilde_NFW(k)     [Msun] = [9.98998564e+13 9.05346969e+13 8.91993930e+12]
rho_tilde_Einasto(k) [Msun] = [1.83204136e+14 1.06342641e+14 9.27420738e+12]

This is one section of the same notebook every Theory page’s own example pulls from — see examples/getting_started.ipynb in the repository for the full runnable notebook, one section per physical effect, from the cosmology through the covariance.

API Reference

For a detailed breakdown of every class and function, see the API Reference.

Additional Resources

Getting Started