Skip to main content

Schechter galaxy luminosity distribution for NumPyro.

Project description

numpyro_schechter

Schechter galaxy luminosity distribution for NumPyro

Schechter distribution logo for numpyro_schechter

Python Versions Docs Status PyPI MIT License Tests


Overview

numpyro_schechter provides NumPyro-compatible probability distributions for Bayesian inference with Schechter and double Schechter luminosity functions in absolute magnitude space.

Built for astronomers and statisticians, it includes a JAX-compatible, differentiable implementation of the upper incomplete gamma function, enabling stable and efficient modelling in probabilistic programming frameworks.


Parameter Constraints

Due to the custom normalisation logic, some constraints apply:

  • alpha must be real and non-integer.
  • The valid range of alpha + 1 depends on alpha_domain_depth. By default, alpha_domain_depth=3, which supports the domain -3 < alpha + 1 < 3.
  • To model more extreme values of alpha, increase the alpha_domain_depth parameter (see below).
  • The list of valid depths is fixed and can be queried programmatically:
    from numpyro_schechter import SchechterMag
    SchechterMag.supported_depths()
    # -> [3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 30]
    
  • If you set include_poisson_term=True, the log-likelihood will also include a Poisson term for the total number counts, with expectation N_exp = norm * volume. The volume argument defaults to 1.0 but can be set to your survey volume.

Installation

From PyPI:

pip install numpyro_schechter

From GitHub (latest development version):

pip install git+https://github.com/alserene/numpyro_schechter.git

Usage

Single Schechter Example

Here is a minimal example showing how to use the SchechterMag distribution:

import jax.numpy as jnp
import numpyro
import numpyro.distributions as dist
from numpyro_schechter.distribution import SchechterMag

# Simulated observed magnitudes
mag_obs = jnp.linspace(-24, -18, 100)

def model(mag_obs):
    # Priors
    alpha = numpyro.sample("alpha", dist.Uniform(-3.0, 1.0))
    M_star = numpyro.sample("M_star", dist.Uniform(-24.0, -20.0))
    logphi = numpyro.sample("logphi", dist.Normal(-3.0, 1.0))

    # Custom likelihood using the SchechterMag distribution, fitting only
    # the shape. Adding include_poisson_term=True would include total counts.
    # See Double Schechter Example for fitting both shape and total count.
    schechter_dist = SchechterMag(alpha=alpha, M_star=M_star, logphi=logphi,
                                  mag_obs=mag_obs)
    
    # Manually inject log-likelihood of observed magnitudes.
    # Required because SchechterMag/DoubleSchechterMag are custom distributions.
    log_likelihood = jnp.sum(schechter_dist.log_prob(mag_obs))
    numpyro.factor("likelihood", log_likelihood)

# You can now run inference with NumPyro's MCMC
# e.g., numpyro.infer.MCMC(...).run(rng_key, model, mag_obs=...)

# Note: Sampling is not implemented for SchechterMag or DoubleSchechterMag;
# it is intended for use as a likelihood in inference.

Double Schechter Example

The double Schechter function is the sum of two Schechter components, each with their own parameters $(\alpha, M^*, \phi^*)$, normalised together over the observed magnitude range:

$$ \phi_{\text{double}}(M) = \frac{\phi_1(M) + \phi_2(M)}{\phi_1^* \Gamma_1 + \phi_2^* \Gamma_2} $$

where $\Gamma_i$ is the upper incomplete gamma function for component $i$.

import jax.numpy as jnp
import numpyro
import numpyro.distributions as dist
from numpyro_schechter import DoubleSchechterMag

def double_schechter_model(mag_obs, volume):
    # Slopes
    alpha1 = numpyro.sample("alpha1", dist.TruncatedNormal(-0.3, 0.1, low=-1.5, high=0.5))
    alpha2 = numpyro.sample("alpha2", dist.TruncatedNormal(-1.3, 0.1, low=-2.5, high=-0.5))

    # Normalisations (log10 φ*)
    logphi1 = numpyro.sample("logphi1", dist.Normal(-2.5, 0.3))
    logphi2 = numpyro.sample("logphi2", dist.Normal(-3.0, 0.3))

    # Break magnitudes
    M_star1 = numpyro.sample("M_star1", dist.TruncatedNormal(-21.0, 0.5, low=-23.0, high=-19.0))
    M_star2 = numpyro.sample("M_star2", dist.TruncatedNormal(-21.5, 0.5, low=-23.5, high=-19.5))

    # Likelihood: includes both point term and Poisson count term to fit
    # both shape and total count. If include_poisson_term=True, then volume
    # is used to scale expected counts and defaults to 1.0.
    dbl_schechter_dist = DoubleSchechterMag(alpha1, M_star1, logphi1,
                                    alpha2, M_star2, logphi2,
                                    mag_obs=mag_obs,
                                    include_poisson_term=True,
                                    volume=volume)

    # Manually inject log-likelihood of observed magnitudes.
    # Required because SchechterMag/DoubleSchechterMag are custom distributions.
    log_likelihood = jnp.sum(dbl_schechter_dist.log_prob(mag_obs))
    numpyro.factor("likelihood", log_likelihood)

# --- Example MCMC runner (same approach can be used for SchechterMag)
# from numpyro.infer import MCMC, NUTS
# mcmc = MCMC(NUTS(double_schechter_model), num_warmup=1000, num_samples=2000)
# mcmc.run(rng_key, mag_obs=your_magnitude_array, volume=your_survey_volume)
# samples = mcmc.get_samples()

For detailed usage and API documentation, please visit the Documentation.


Development

If you want to contribute or develop locally:

git clone https://github.com/alserene/numpyro_schechter.git
cd numpyro_schechter
poetry install
poetry run pytest

License

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


Contact

Created by


Happy modelling!

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

numpyro_schechter-1.1.0.tar.gz (7.6 kB view details)

Uploaded Source

Built Distribution

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

numpyro_schechter-1.1.0-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file numpyro_schechter-1.1.0.tar.gz.

File metadata

  • Download URL: numpyro_schechter-1.1.0.tar.gz
  • Upload date:
  • Size: 7.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.1 CPython/3.12.3 Darwin/23.6.0

File hashes

Hashes for numpyro_schechter-1.1.0.tar.gz
Algorithm Hash digest
SHA256 32435cc0e999640b40140b8fa177be7900715095b61bea6581ae740f2cb9cbb2
MD5 d08ccd08d817c12e4e67fd937b4b26bd
BLAKE2b-256 4b867dcba7608255be56fee5a7c825bf68e7e280ebf1ba3bfb13f0163acc3185

See more details on using hashes here.

File details

Details for the file numpyro_schechter-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: numpyro_schechter-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.1 CPython/3.12.3 Darwin/23.6.0

File hashes

Hashes for numpyro_schechter-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5b45601c96254e04db5006622f0b424822796d57e94385669d1a8b6bfa377af5
MD5 df10096d0328af09eddbbb281275f65d
BLAKE2b-256 2946b3007670792664023e5515dd1661bb7adda6b17be1125232ee135671b5bd

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