Skip to main content

UV Luminosity Function and Halo Occupation Distribution modeling for high-redshift galaxies

Project description

halogal

Python Version License: MIT

A Python package for modeling UV luminosity functions and galaxy clustering using Halo Occupation Distribution (HOD) models for high-redshift galaxies.

Features

  • Simple API: Only redshift required, scientifically validated defaults
  • UV-Halo Mass Relation (UVHMR): Connect halo mass to UV luminosity through star formation
  • Halo Occupation Distribution: Model central and satellite galaxy populations
  • Luminosity Functions: Compute UV luminosity functions at high redshift
  • Galaxy Bias: Calculate galaxy clustering bias
  • Correlation Functions: Angular, real-space, and projected 2PCFs via halomod
  • Efficient Parameter Updates: All observables accept inline **params for fast MCMC loops
  • Dust Attenuation: Self-consistent treatment following Bouwens+2013-14
  • Fitted Parameters: Defaults from Shuntov+2025
  • Redshift Evolution: Built-in parameter evolution with redshift

Installation

From PyPI (when published)

pip install halogal

From source

git clone https://github.com/mshuntov/halogal.git
cd halogal
pip install -e .

Dependencies

  • numpy >= 1.20
  • scipy >= 1.7
  • astropy >= 5.0
  • colossus >= 1.3
  • halomod >= 1.4

Quick Start

Minimal Example

import numpy as np
from halogal import HODModel
from halogal.model import Observables

# Create model — only redshift required!
# Uses fitted defaults from Shuntov+2025
model = HODModel(z=6.0)
obs = Observables(model)

# Compute luminosity function
MUV = np.linspace(-22, -16, 20)
phi = obs.luminosity_function(MUV)

Galaxy Bias

bias = obs.galaxy_bias(MUV)

UV-Halo Mass Relation

# UVHMR methods live directly on the model
Mh = 1e11  # M_sun
MUV = model.MUV(Mh)
sfr = model.sfr(Mh)

print(f"Halo mass {Mh:.2e} M_sun:")
print(f"  M_UV = {MUV:.2f}")
print(f"  SFR = {sfr:.1f} M_sun/yr")

# Inverse relation
Mh_recovered = model.Mhalo(MUV)

Override Specific Parameters

# At construction
model = HODModel(z=6.0, eps0=0.25, sigma_UV=0.5)
obs = Observables(model)

# Or inline when computing observables — no need to recreate anything
phi = obs.luminosity_function(MUV, eps0=0.3, sigma_UV=0.6)

Efficient MCMC Fitting

All observable methods on Observables accept **params keyword arguments to update the underlying model in-place before computing. This avoids object re-creation in tight loops:

obs = Observables(HODModel(z=6.0))
MUV = np.linspace(-22, -16, 20)

for eps0, sigma_UV in mcmc_samples:
    phi  = obs.luminosity_function(MUV, eps0=eps0, sigma_UV=sigma_UV)
    bg   = obs.galaxy_bias(MUV, eps0=eps0, sigma_UV=sigma_UV)
    mh   = obs.mean_halo_mass(-19.0, eps0=eps0, sigma_UV=sigma_UV)
    ngal = obs.number_density(-19.0, eps0=eps0, sigma_UV=sigma_UV)

For correlation functions, use the initialize/update pattern which leverages halomod's internal caching:

obs = Observables(HODModel(z=6.0))

# Initialize once (expensive)
result = obs.initialize_correlation_model(
    MUV_thresh1=-19.1, correlation_type='angular'
)

# Update efficiently in MCMC loop
for eps0, sigma_UV in mcmc_samples:
    result = obs.update_correlation_model(eps0=eps0, sigma_UV=sigma_UV)
    w_theta = result['correlation']
    theta   = result['separation']

Redshift Evolution

from halogal.models.parametrization import eps0_fz, Mc_fz
from halogal.config import DEFAULT_REDSHIFT_EVOLUTION

z_array = np.linspace(4, 8, 20)

# Get evolved parameters
eps0_z = eps0_fz(
    z_array, 
    deps_dz=DEFAULT_REDSHIFT_EVOLUTION['d_eps0_dz'],
    eps_off=DEFAULT_REDSHIFT_EVOLUTION['C_eps0']
)

Mc_z = 10**Mc_fz(
    z_array,
    dMc_dz=DEFAULT_REDSHIFT_EVOLUTION['d_logMc_dz'],
    Mc_off=DEFAULT_REDSHIFT_EVOLUTION['C_logMc']
)

# Compute with evolved parameters inline
obs = Observables(HODModel(z=z_array[0]))
for z, eps0, Mc in zip(z_array, eps0_z, Mc_z):
    phi = obs.luminosity_function(MUV, eps0=eps0, Mc=Mc)

Compare to Observations

from bouwens21_data import bouwens21, redshift_centers

data = bouwens21['z6']
z_obs = redshift_centers['z6']

obs = Observables(HODModel(z=z_obs))
MUV_model = np.linspace(-23, -15, 50)
phi_model = obs.luminosity_function(MUV_model)

plt.errorbar(data['M_AB'], data['Fi_k'], yerr=data['Fi_k_error'],
            fmt='o', label='Bouwens+2021')
plt.semilogy(MUV_model, phi_model, '-', label='Model')
plt.legend()
plt.show()

Documentation

Full documentation is available at https://uvlf-hod.readthedocs.io/en/latest/#.

Package Structure

halogal/
├── __init__.py          # Public API
├── config.py            # Configuration and defaults
├── cosmology.py         # Halo mass function and bias
├── model.py             # Unified UVHMR, HOD, and Observables
├── luminosity.py        # UV luminosity and dust
└── models/
    └── parametrization.py  # Redshift parametrizations

Key Classes

  • HODModel: Galaxy population model combining UVHMR + HOD (parameters and occupation functions)
  • Observables: Compute observables (UVLF, bias, correlation functions) from an HODModel; supports efficient inline parameter updates via **params
  • UVHMRModel: Base class for UV-halo mass relations only

Model Architecture

UVHMRModel (base class)
├── Handles UV-halo mass relations
├── Methods: sfr(), MUV(), Mhalo(), star_formation_efficiency()
└── Parameters: z (required), eps0, Mc, a, b (optional)

HODModel (extends UVHMRModel)
├── Inherits all UVHMR methods
├── Adds occupation distributions: Ncen(), Nsat(), Ngal()
└── Additional parameters: sigma_UV, Mcut, Msat, asat (optional)

Observables (takes an HODModel)
├── luminosity_function(MUV, **params)
├── galaxy_bias(MUV, **params)
├── mean_halo_mass(MUV_thresh, **params)
├── mean_bias(MUV_thresh, **params)
├── number_density(MUV_thresh, **params)
├── initialize_correlation_model() / update_correlation_model()
└── compute_correlation_function()

All Observables methods accept **params (eps0, Mc, a, b, sigma_UV, Mcut, Msat, asat) to update the model inline before computing.

Default Parameters

All defaults from Shuntov+2025 (2025A&A...699A.231S) at z~5.4:

UVHMR Parameters

Parameter Default Description
eps0 0.19 Star formation efficiency
Mc 10^11.64 M_☉ Characteristic halo mass
a 0.69 Low-mass slope
b 0.65 High-mass slope

HOD Parameters

Parameter Default Description
sigma_UV 0.69 mag UV magnitude scatter
Mcut 10^9.57 M_☉ Satellite cutoff mass
Msat 10^12.65 M_☉ Satellite normalization
asat 0.85 Satellite power-law slope

Redshift Evolution

All parameters evolve as: param(z) = d_param/dz × z + C_param

Evolution parameters available in DEFAULT_REDSHIFT_EVOLUTION.

Examples

See the examples/ directory for detailed examples:

  • basic_usage.ipynb: Interactive Jupyter notebook with complete workflow
  • bouwens21_data.py: Observational data compilation

Testing

Run tests with pytest:

pytest tests/

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. Submit a pull request

Citation

If you use this package in your research, please cite:

@ARTICLE{2025A&A...699A.231S,
       author = {{Shuntov}, Marko and {Oesch}, Pascal A. and {Toft}, Sune and {Meyer}, Romain A. and {Covelo-Paz}, Alba and {Paquereau}, Louise and {Bouwens}, Rychard and {Brammer}, Gabriel and {Gelli}, Viola and {Giovinazzo}, Emma and {Herard-Demanche}, Thomas and {Illingworth}, Garth D. and {Mason}, Charlotte and {Naidu}, Rohan P. and {Weibel}, Andrea and {Xiao}, Mengyuan},
        title = "{Constraints on the early Universe star formation efficiency from galaxy clustering and halo modeling of H{\ensuremath{\alpha}} and [O III] emitters}",
      journal = {\aap},
     keywords = {galaxies: evolution, galaxies: high-redshift, galaxies: luminosity function, mass function, galaxies: statistics, Astrophysics of Galaxies},
         year = 2025,
        month = jul,
       volume = {699},
          eid = {A231},
        pages = {A231},
          doi = {10.1051/0004-6361/202554618},
archivePrefix = {arXiv},
       eprint = {2503.14280},
 primaryClass = {astro-ph.GA},
       adsurl = {https://ui.adsabs.harvard.edu/abs/2025A&A...699A.231S},
      adsnote = {Provided by the SAO/NASA Astrophysics Data System}
}

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Based on methodology from:

  • Shuntov et al. 2025, A&A 699 A321
  • Sabti et al. 2022
  • Muñoz et al. 2023
  • Bouwens et al. 2013, 2014
  • And others...

Contact

For questions or issues, please open an issue on GitHub or contact marko.shuntov@nbu.ku.dk.

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

halogal-0.1.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

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

halogal-0.1.0-py3-none-any.whl (1.0 MB view details)

Uploaded Python 3

File details

Details for the file halogal-0.1.0.tar.gz.

File metadata

  • Download URL: halogal-0.1.0.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.7.12

File hashes

Hashes for halogal-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4d834b96b107557548b9441406e592349b7ed1d469704096aa3bc21f86d22b9e
MD5 8a3c3ad7776ef6d569b0d393a9621331
BLAKE2b-256 c4a102c4028b2e09256542856a18d4288491b84b157feea2768f80b8189e7544

See more details on using hashes here.

File details

Details for the file halogal-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: halogal-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.7.12

File hashes

Hashes for halogal-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4301ec52707f14d4bab97add34d6810248a8a21ee10f71adc381b771ede47282
MD5 89f671f946bdc15de945e83eb31797f4
BLAKE2b-256 8b3e4badea6f10162cdac3b227ffcaabcf14b31b4b39020cc3df060170fa3636

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