Fitting with the More+2015 HOD Model
Overview
hod_mod/scripts/fitting/run_fit_More15.py (also hod-mod fit) is a command-line tool for fitting
the FullHaloModelPrediction forward model to
observational data using the More et al. (2015)
Halo Occupation Distribution (HOD) model.
The script is a thin wrapper around the validated fitting classes in
hod_mod.fitting:
WpFitter— projected clustering \(w_p(r_p)\) onlyDeltaSigmaFitter— excess surface density \(\Delta\Sigma(R)\) onlyJointFitter— joint \(w_p + \Delta\Sigma + n_\mathrm{gal}\)
The probe mode is detected automatically from the YAML configuration (see Probe Modes).
Quick Start
Step 1 — Write a configuration file (see examples in configs/fitting/):
label: "My galaxy sample"
data:
file: path/to/wp_data.csv
format: bwpd
rp_min: 0.5
rp_max: 50.0
cosmology:
Omega_m: 0.310
h: 0.700
sigma8: 0.800
n_s: 0.965
Omega_b: 0.045
model:
hod_model: MoreHODModel
hmf_backend: tinker08
z: 0.50
pi_max: 100.0
parameters:
log10mmin: {free: true, bounds: [11.0, 15.0], init: 12.5}
sigma_logm: {free: true, bounds: [0.05, 1.50], init: 0.4}
log10m1: {free: true, bounds: [12.0, 15.5], init: 13.5}
alpha: {free: true, bounds: [0.50, 2.50], init: 1.0}
kappa: {free: true, bounds: [0.01, 3.00], init: 1.0}
fitting:
method: map
output:
dir: results/my_fit/
Step 2 — Run:
python hod_mod/scripts/fitting/run_fit_More15.py config.yml --map-only
Step 3 — Check outputs in results/my_fit/:
fit_result.json # best-fit params, χ²/dof
fit_wp.png # wp data vs best-fit
fit_combined.png # rp·wp panel
fit_hod.png # N_c(M), N_s(M) occupation
YAML Configuration Reference
data: block (wp)
Required when fitting \(w_p(r_p)\).
Field |
Type |
Default |
Description |
|---|---|---|---|
|
string |
— |
Path to \(w_p\) data file (CSV, HDF5, or FITS). |
|
string |
— |
Data format. |
|
float |
0.0 |
Minimum \(r_p\) (\(h^{-1}\) Mpc) to include in fit. |
|
float |
∞ |
Maximum \(r_p\) (\(h^{-1}\) Mpc) to include in fit. |
joint: block (ESD + n_gal)
Include to activate joint \(w_p + \Delta\Sigma + n_\mathrm{gal}\) fitting. Omitting this block makes the fit wp-only.
Field |
Type |
Default |
Description |
|---|---|---|---|
|
string |
— |
Path to \(\Delta\Sigma\) data file. |
|
string |
— |
ESD format. |
|
float |
0.0 |
Minimum \(R\) (\(h^{-1}\) Mpc) for ESD. |
|
float |
∞ |
Maximum \(R\) (\(h^{-1}\) Mpc) for ESD. |
|
float |
— |
Observed galaxy number density \(h^3\) Mpc:math:^{-3}. |
|
float |
0.20 |
Fractional error on \(n_\mathrm{gal}\) (Gaussian term in likelihood). |
ds: block (ESD-only mode)
Use ds: instead of joint: to fit \(\Delta\Sigma\) only (without \(w_p\)).
The fields are identical to the joint: block above.
cosmology: block
Field |
Type |
Required |
Description |
|---|---|---|---|
|
float |
yes |
Total matter density parameter at z=0. |
|
float |
yes |
Dimensionless Hubble constant (\(H_0 = 100\,h\) km/s/Mpc). |
|
float |
yes |
RMS matter fluctuations at 8 \(h^{-1}\) Mpc. |
|
float |
yes |
Primordial spectral index. |
|
float |
yes |
Baryon density parameter. |
model: block
Field |
Type |
Default |
Description |
|---|---|---|---|
|
string |
|
HOD model class. Use |
|
string |
|
Halo mass function backend. |
|
float |
— |
Galaxy sample effective redshift. |
|
float |
100.0 |
Line-of-sight integration limit \(\pi_\mathrm{max}\) (Mpc/\(h\)). |
|
bool |
|
Enable beyond-linear halo bias (Mead & Verde 2021). Negligible at \(r_p > 1\,h^{-1}\) Mpc. |
parameters: block
Each entry: name: {free: bool, bounds: [lo, hi], init: value}.
If free: false, only init is required (the parameter is held fixed).
fitting: block
Field |
Type |
Default |
Description |
|---|---|---|---|
|
string |
|
|
|
int |
32 |
Number of emcee walkers. |
|
int |
2000 |
Number of MCMC steps per walker. |
|
int |
500 |
Burn-in steps discarded before saving the flat chain. |
output: block
Field |
Type |
Default |
Description |
|---|---|---|---|
|
string |
|
Directory for all output files. |
label: (top-level)
Optional string identifying this fit in figure titles and JSON output. Defaults to the YAML filename stem if absent.
published_params: (top-level, optional)
Dictionary mapping parameter names to [best-fit, error] pairs.
When present, a dashed reference curve is overlaid on all data comparison plots,
and MCMC corner plots mark the reference values as vertical/horizontal lines.
Example:
published_params:
log10mmin: [13.13, 0.13]
sigma_logm: [0.469, 0.13]
log10m1: [14.21, 0.12]
alpha: [1.130, 0.09]
kappa: [1.250, 0.40]
Probe Modes
The fitter class is selected automatically based on which data sections appear in the YAML:
Probes in config |
Fitter class |
Likelihood |
|---|---|---|
|
|
\(\chi^2_{w_p}\) |
|
|
\(\chi^2_{\Delta\Sigma}\) |
|
|
\(\chi^2_{w_p} + \chi^2_{\Delta\Sigma} + \chi^2_{n_\mathrm{gal}}\) |
Covariance Options
Diagonal covariance (CSV / bwpd format)
When data.file is a CSV with bwpd or bwpd_4col format, the
covariance is diagonal: \(C_{ii} = \sigma_i^2\) from the error column.
This is appropriate when data points are independently measured or when
off-diagonal correlations are negligible.
Full covariance (HDF5/FITS jackknife)
When the data file is an HDF5/FITS jackknife catalogue, load_config()
builds the full jackknife covariance matrix and applies the
Hartlap et al. (2007) correction:
To use jackknife data, provide either:
data:
file: path/to/wp_jackknife.h5
format: hdf5
or the jackknife patch directory:
fits:
jk_dir: data/my_survey/jk_patches/
jk_pattern: NSIDE_04
h: 0.6736
Command-Line Options
python hod_mod/scripts/fitting/run_fit_More15.py <config.yml> [options]
Positional argument:
config Path to YAML configuration file.
Options:
--map-only Run MAP optimisation only (skip MCMC even if config says
method=both or method=mcmc).
--mcmc Run MAP then MCMC sampling (overrides method=map in config).
--plot-only Skip fitting; reload fit_result.json and regenerate figures.
--output-dir DIR Override the output directory from the config.
Output Files
File |
Description |
|---|---|
|
JSON with label, probes, chi2, ndof, chi2/ndof, success flag, all parameter values. |
|
MCMC flat chain (after burn-in). Arrays: |
|
\(w_p(r_p)\) data vs MAP prediction with residuals; MCMC bands if available. |
|
\(\Delta\Sigma(R)\) data vs MAP prediction with residuals (joint/ESD modes). |
|
\(r_p\,w_p\) and \(\Delta\Sigma\) side by side with residuals. |
|
\(N_c(M)\) and \(N_s(M)\) at MAP; MCMC occupation credible bands if available. |
|
MCMC corner plot with 1σ/2σ contours; reference values from |
Parameter Reference
More+2015 HOD Parameters
The More et al. (2015) model has five free parameters describing central and satellite occupation:
Name |
Units |
Physical meaning |
|---|---|---|
|
\(\log_{10}(M_\odot/h)\) |
Halo mass scale at which 50% of halos host a central galaxy. Controls the overall HOD amplitude and galaxy number density. |
|
dex |
Width of the central occupation step function (log-normal scatter in SHMR). Larger values lower the effective halo mass threshold. |
|
\(\log_{10}(M_\odot/h)\) |
Characteristic satellite mass scale — halos above \(M_1\) host on average one satellite. |
|
— |
Slope of the satellite mean occupation power law \(N_s \propto (M/M_1)^\alpha\). |
|
— |
Threshold multiplicative factor: satellites only occupy halos above \(\kappa\,M_\mathrm{min}\). |
Off-centering Parameters
Fixed by default to the More+2015 published MAP values; can be freed.
Name |
Units |
Physical meaning |
|---|---|---|
|
— |
Fraction of central galaxies miscentred from the halo centre. |
|
\(r_s\) units |
Off-centering radial scale in units of the NFW scale radius \(r_s(M)\). A value of 2.2 means off-centred galaxies are displaced by \(2.2\,r_s\) on average. |
Incompleteness Parameters
Set free: false and init: 1.0 / 13.0 to disable incompleteness correction.
Name |
Units |
Physical meaning |
|---|---|---|
|
— |
Incompleteness power-law slope. |
|
\(\log_{10}(M_\odot/h)\) |
Halo mass scale for incompleteness onset. |
Example: wp-only MAP
Configuration file configs/fitting/More15_wp_example.yml:
# Example: More+2015 HOD model fit to wp(rp) only — BOSS CMASS sample A (logM*>11.1)
# Run:
# python hod_mod/scripts/fitting/run_fit_More15.py \
# configs/fitting/More15_wp_example.yml --map-only
#
# Data from More+2015 (arXiv:1407.1856) Table 3 sample A, digitised
# Cosmology fixed to published MAP values
label: "More+2015 BOSS CMASS logM11 — wp-only MAP"
data:
file: data/more2015_boss_cmass/logM11_12/wp_logM11_12.csv
format: bwpd
rp_min: 0.85
rp_max: 80.0
cosmology:
Omega_m: 0.310
h: 0.703
sigma8: 0.785
n_s: 0.964
Omega_b: 0.0451
model:
hod_model: MoreHODModel
hmf_backend: csst
z: 0.53
pi_max: 100.0
parameters:
log10mmin: {free: true, bounds: [12.0, 15.0], init: 13.13}
sigma_logm: {free: true, bounds: [0.05, 1.50], init: 0.469}
log10m1: {free: true, bounds: [13.0, 15.5], init: 14.21}
alpha: {free: true, bounds: [0.50, 2.50], init: 1.13}
kappa: {free: true, bounds: [0.01, 3.00], init: 1.25}
alpha_inc: {free: false, init: 1.0}
log10m_inc: {free: false, init: 13.0}
p_off: {free: false, init: 0.34}
R_off: {free: false, init: 2.2}
fitting:
method: map
n_walkers: 32
n_steps: 2000
n_burnin: 500
output:
dir: results/fitting/More15_wp_example/
# Optional: overlay published best-fit values on plots (dashed reference line)
published_params:
log10mmin: [13.13, 0.13]
sigma_logm: [0.469, 0.13]
log10m1: [14.21, 0.12]
alpha: [1.130, 0.09]
kappa: [1.250, 0.40]
Run:
python hod_mod/scripts/fitting/run_fit_More15.py \
configs/fitting/More15_wp_example.yml --map-only
Expected output:
============================================================
run_fit_More15 [More+2015 BOSS CMASS logM11 — wp-only MAP]
Config: configs/fitting/More15_wp_example.yml
Probes: wp
Free params (5): ['log10mmin', 'sigma_logm', 'log10m1', 'alpha', 'kappa']
Output: results/fitting/More15_wp_example/
============================================================
Fit: More+2015 BOSS CMASS logM11 — wp-only MAP
============================================================
chi2 / ndof = 42.892 / 22 → chi2/dof = 1.950
Optimizer: OK
Best-fit parameters:
log10mmin = 13.191 (free)
sigma_logm = 0.5110 (free)
log10m1 = 14.196 (free)
alpha = 1.8605 (free)
kappa = 2.6753 (free)
alpha_inc = 1.0
log10m_inc = 13.0
p_off = 0.34
R_off = 2.2
Result saved → results/fitting/More15_wp_example/fit_result.json
=== Generating figures ===
Saved: results/fitting/More15_wp_example/fit_wp.png
...
Example: joint MAP + MCMC
Configuration file configs/fitting/More15_joint_example.yml:
# Example: More+2015 HOD model joint fit to wp(rp) + ΔΣ(R) + n_gal
# Run MAP only:
# python hod_mod/scripts/fitting/run_fit_More15.py \
# configs/fitting/More15_joint_example.yml --map-only
#
# Run MAP + MCMC:
# python hod_mod/scripts/fitting/run_fit_More15.py \
# configs/fitting/More15_joint_example.yml --mcmc
#
# Data from More+2015 (arXiv:1407.1856) sample A (logM*>11.1), digitised
# Cosmology fixed to published MAP values
label: "More+2015 BOSS CMASS logM11 — joint wp+ESD MAP+MCMC"
data:
file: data/more2015_boss_cmass/logM11_12/wp_logM11_12.csv
format: bwpd
rp_min: 0.85
rp_max: 80.0
joint:
ds_file: data/more2015_boss_cmass/logM11_12/ds_logM11_12.csv
ds_format: bwpd_4col
ds_rp_min: 0.1
ds_rp_max: 20.0
ng_obs: 3.0e-4
ng_frac_err: 0.20
cosmology:
Omega_m: 0.310
h: 0.703
sigma8: 0.785
n_s: 0.964
Omega_b: 0.0451
model:
hod_model: MoreHODModel
hmf_backend: csst
z: 0.53
pi_max: 100.0
parameters:
log10mmin: {free: true, bounds: [12.0, 15.0], init: 13.13}
sigma_logm: {free: true, bounds: [0.05, 1.50], init: 0.469}
log10m1: {free: true, bounds: [13.0, 15.5], init: 14.21}
alpha: {free: true, bounds: [0.50, 2.50], init: 1.13}
kappa: {free: true, bounds: [0.01, 3.00], init: 1.25}
alpha_inc: {free: false, init: 1.0}
log10m_inc: {free: false, init: 13.0}
p_off: {free: false, init: 0.34}
R_off: {free: false, init: 2.2}
fitting:
method: both # MAP first, then MCMC
n_walkers: 32
n_steps: 2000
n_burnin: 500
output:
dir: results/fitting/More15_joint_example/
# Optional: overlay published best-fit values on plots (dashed reference line)
published_params:
log10mmin: [13.13, 0.13]
sigma_logm: [0.469, 0.13]
log10m1: [14.21, 0.12]
alpha: [1.130, 0.09]
kappa: [1.250, 0.40]
Run MAP then MCMC sampling:
python hod_mod/scripts/fitting/run_fit_More15.py \
configs/fitting/More15_joint_example.yml --mcmc
Or run MAP only first to check convergence, then add MCMC:
# Quick MAP check
python hod_mod/scripts/fitting/run_fit_More15.py \
configs/fitting/More15_joint_example.yml --map-only
# Regenerate figures from saved result
python hod_mod/scripts/fitting/run_fit_More15.py \
configs/fitting/More15_joint_example.yml --plot-only
The joint likelihood is:
where
References
More, S., van den Bosch, F. C., Cacciato, M., et al. 2015, ApJ, 806, 2. arXiv:1407.1856
Tinker, J. L., Kravtsov, A. V., Klypin, A., et al. 2008, ApJ, 688, 709. arXiv:0803.2706
Hartlap, J., Simon, P., & Schneider, P. 2007, A&A, 464, 399. arXiv:astro-ph/0608064
Mead, A. J., & Verde, L. 2021, MNRAS, 503, 3095. arXiv:2009.10724