Skip to main content

HOD galaxy clustering and weak lensing prediction and fitting

Project description

hod_mod

JAX-accelerated HOD galaxy clustering, weak lensing, and gas cross-correlation predictions and fitting.

CI Tests Coverage Docs PyPI version Python License: MIT Data DOI

Overview

hod_mod is a Python 3.11+ package for forward-modelling galaxy clustering (w_p), weak gravitational lensing (ΔΣ), and galaxy × gas cross-correlations (tSZ Compton-y, soft X-ray) from Halo Occupation Distribution (HOD) and inverse-SHMR (iHOD) models. All numerical code is JAX-native, enabling automatic differentiation and JIT compilation for efficient MCMC inference.

Install

Available on PyPI:

pip install hod-mod

For development, create and activate the conda environment then install in editable mode:

# Download the installer (Linux x86_64)
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh

# Run the installer (follow prompts, accept defaults)
bash Miniforge3-Linux-x86_64.sh

# Reload shell
source ~/.bashrc
mamba env create -f environment.yml
mamba activate hod_mod
pip install -e .
pre-commit install          # optional: blocks committing large files / results/

Data and benchmark results

Small reference data needed to run the models ships inside the package. Large inputs and the curated benchmark results (final MCMC chains, headline figures) are archived on Zenodo and fetched on demand — the git repository stays lean.

  • Dataset: 10.5281/zenodo.21078473 (concept DOI — always resolves to the latest version)
  • Downloads are checksum-verified and cached locally with pooch (a dependency, installed automatically).
from hod_mod.data_io import fetch

# downloads from Zenodo + verifies the checksum on first call; cache hit afterwards
chain = fetch("results/benchmarks/more2015_logM11_12/flatchain.npz")

See docs/data_hosting.rst for the full strategy and the upload/registry workflow.

Environment variables

All filesystem locations are resolved through hod_mod.paths — there are no hardcoded paths in the code. Each helper reads an env var and falls back to a sensible default, so a fresh checkout runs without configuration, and your machine's layout is set once in ~/.bashrc.

Variable Helper Points to Default
HOD_MOD_REPO repo_root() code repository (configs/, in-repo data/) auto-detected from the package
HOD_MOD_DATA_DIR data_root() the data repository (external inputs: zenodo/, erosita/, legacysurvey/, st_mod_data/, xray_bands/) hod_mod/data
HOD_MOD_SUMSTAT sum_stat_root() sum_stat measurement products ~/software/sum_stat/data
HOD_MOD_RESULTS results_root() generated outputs (chains, figures) — never in the repo ~/.local/share/hod_mod/results
HOD_MOD_CACHE cache_root() JAX/XLA compilation caches OS user-cache dir
HOD_MOD_DATA_DOI pin a specific Zenodo version (default: pinned in code) concept DOI

Recommended ~/.bashrc setup:

export HOD_MOD_REPO="$HOME/software/hod_mod"
export HOD_MOD_DATA_DIR="$HOME/data"
export HOD_MOD_SUMSTAT="$HOME/software/sum_stat/data"
export HOD_MOD_RESULTS="$HOME/data/hod_mod_results"
from hod_mod.paths import repo_root, data_root, sum_stat_root, results_root
print(repo_root(), data_root(), sum_stat_root(), results_root())

Tests

pytest                             # run all tests
pytest tests/test_cosmology.py    # single module
pytest -x                         # stop on first failure
pytest -v                         # verbose output
pytest --tb=short                 # compact tracebacks

The test suite covers cosmology, HOD models, gas profiles, clustering predictions, cross-spectra, data I/O, and fitting. Tests that require optional backends (camb, colossus) are skipped automatically if those packages are absent.

Supported HOD models

Class Reference
HODModel Zheng et al. 2007
MoreHODModel More et al. 2015 (BOSS CMASS)
Kravtsov04HODModel Kravtsov et al. 2004
Guo18ICSMFModel Guo et al. 2018
Guo19ICSMFModel Guo et al. 2019 (eBOSS ELGs)
Zacharegkas25HODModel Zacharegkas et al. 2025
VanUitert16CSMFModel van Uitert et al. 2016
ZuMandelbaum15HODModel Zu & Mandelbaum 2015 (iHOD)
ZuMandelbaum16QuenchingModel Zu & Mandelbaum 2016
Leauthaud12HODModel Leauthaud et al. 2012

All clustering HOD classes subclass HODBase (ABC) and implement nc_ns() and default_params().

Gas profiles and cross-correlations

hod_mod predicts galaxy × gas cross-correlations using parametric electron pressure and density profiles embedded in the same halo model framework.

Gas profile classes (hod_mod.gas):

Class Physical profile Reference
PressureProfileA10 electron pressure P_e(r|M,z) → tSZ Compton-y Arnaud et al. 2010
GasDensityDPM (model=1,2,3) electron density n_e(r|M,z) → soft X-ray ε Oppenheimer et al. 2025
m200_to_m500c NFW bisection: M₂₀₀ → M₅₀₀c, R₅₀₀c

Cross-spectrum observables (hod_mod.observables.cross_spectra):

Method Observable Units
_pk_tables_gy P_{g,y}(k), P_{m,y}(k), 1h+2h (Mpc/h)²
_pk_tables_gX P_{g,X}(k), 1h+2h (Mpc/h)³ cm⁻⁶
projected_gy Σ_y(r_p) stacked tSZ profile dimensionless Compton-y
projected_gX w_{g,X}(r_p) stacked X-ray profile (Mpc/h) cm⁻⁶
angular_cl_gy C_ℓ^{g,y} via Limber approximation (Mpc/h)²
angular_cl_gX C_ℓ^{g,X} via Limber approximation (Mpc/h) cm⁻⁶
from hod_mod.gas import PressureProfileA10, GasDensityDPM
from hod_mod.observables.cross_spectra import HaloModelCrossSpectra

pp    = PressureProfileA10(r_max_over_r500c=5.0, n_gl=200)   # Arnaud+2010
dp    = GasDensityDPM(model=2, r_max_over_r200=3.0, n_gl=200) # Oppenheimer+2025
cross = HaloModelCrossSpectra(fhmp, pressure_profile=pp, density_profile=dp)

sigma_y = cross.projected_gy(rp, z=0.5, theta_cosmo=theta, hod_params=params)
cl_gy   = cross.angular_cl_gy(ell, z_arr, nz_g, theta, params)
wgX     = cross.projected_gX(rp, z=0.5, theta_cosmo=theta, hod_params=params)

Benchmark data for Comparat et al. 2025 (galaxy × eROSITA 0.5–2 keV, 7 stellar-mass-selected samples, LS DR10 × eRASS:5) is included in hod_mod/data/benchmarks/xray/.

Quick start — clustering and lensing

from hod_mod import (
    LinearPowerSpectrum, make_hmf, HaloProfile,
    MoreHODModel, FullHaloModelPrediction,
)
import jax.numpy as jnp

pk_lin = LinearPowerSpectrum()
theta  = pk_lin.default_cosmology()
hmf    = make_hmf("tinker08", pk_func=pk_lin.pk_linear)

colossus_cosmo = dict(flat=True, H0=67.36, Om0=0.31, Ob0=0.0493, sigma8=0.811, ns=0.965)
hp = HaloProfile(colossus_cosmo, cm_relation="diemer19")

hod    = MoreHODModel(hmf, hmf.bias)
pred   = FullHaloModelPrediction(pk_lin, hod, hp, profile="nfw")

rp     = jnp.logspace(-1, 1.5, 20)
params = MoreHODModel.default_params()
wp     = pred.wp(rp, pi_max=60.0, z=0.5, theta_cosmo=theta, hod_params=params)

"tinker08" is the library's dependency-free default HMF backend. The fitting pipelines under hod_mod/scripts/fitting/ instead use make_hmf("csst") (CSSTEMU) as their baseline — see docs/cosmology.rst for details.

HOD fitting

Run from the repository root (paths in configs are resolved relative to it):

from hod_mod.fitting import load_config, WpFitter

cfg     = load_config("configs/hod_fit_more2015_cmass.yml")
fitter  = WpFitter(cfg)
result  = fitter.map_fit()               # Nelder-Mead MAP → dict
sampler = fitter.sample()               # emcee MCMC → EnsembleSampler
chain   = sampler.get_chain(flat=True)  # shape (n_steps * n_walkers, n_free)

The sample data file data/more2015_boss_cmass/wp_cmass_z052.csv is included in the repository (More+2015, arXiv:1407.1856, Figure 2).

Reproducing published results

Each benchmark paper has a dedicated validation script. Run any script from the repository root:

Paper Script Observable
More et al. 2015 run_benchmark.py --model more2015 w_p(r_p) BOSS CMASS
Lange et al. 2025 run_benchmark.py --model lange2025_bgs3_bwpd_hsc w_p + ΔΣ DESI BGS
Arnaud et al. 2010 validate_arnaud2010.py A10 pressure profile
Oppenheimer et al. 2025 validate_oppenheimer2025.py DPM density profile
Amodeo et al. 2021 validate_amodeo2021.py Σ_y(r_p) BOSS CMASS tSZ
Pandey et al. 2025 validate_pandey2025.py C_ℓ^{g,y} DES × ACT
Comparat et al. 2025 validate_comparat2025.py w_θ(θ) LS DR10 × eROSITA

Run clustering/lensing benchmarks:

# from repo root
python hod_mod/scripts/benchmarks/run_benchmark.py --model more2015 --plot
python hod_mod/scripts/benchmarks/run_all_benchmarks.py --plot

Run gas/cross-correlation validation scripts:

python -m hod_mod.scripts.validate_arnaud2010
python -m hod_mod.scripts.validate_oppenheimer2025
python -m hod_mod.scripts.validate_sz_xray
python -m hod_mod.scripts.validate_amodeo2021
python -m hod_mod.scripts.validate_pandey2025
python -m hod_mod.scripts.validate_comparat2025

Figures are saved to hod_mod/scripts/figures/.

Citation

If you use hod_mod in published work, cite:

Comparat et al. 2025, A&A 697, A173 https://ui.adsabs.harvard.edu/abs/2025A%26A...697A.173C

and this repository URL. Depending on the model used, additionally cite the relevant HOD or gas profile paper(s) from the tables above.

If you use the archived benchmark data or curated results, also cite the dataset: 10.5281/zenodo.21078473.


License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hod_mod-0.2.1.tar.gz (867.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hod_mod-0.2.1-py3-none-any.whl (901.2 kB view details)

Uploaded Python 3

File details

Details for the file hod_mod-0.2.1.tar.gz.

File metadata

  • Download URL: hod_mod-0.2.1.tar.gz
  • Upload date:
  • Size: 867.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for hod_mod-0.2.1.tar.gz
Algorithm Hash digest
SHA256 d5b257396f766623596873814d93e74ade06baa9cf9e0c18172f36fc194b486b
MD5 e351dbd3e46e14b37ec33a44f43dc493
BLAKE2b-256 4f152ae85041e01395a9fbf4f0c616e35d63679f9598b724c07bc1c837b25535

See more details on using hashes here.

File details

Details for the file hod_mod-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: hod_mod-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 901.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for hod_mod-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e5908fe20df504f927b8512b32da03ce9be3f9e064f3ae2b1b247fa5aaa3932a
MD5 3ec34678dfe04f385ef1037b177b0dce
BLAKE2b-256 0feaec13866703b410f656f950cdf71e448a1dfa25824cefe76f31f26ec61d59

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page