Skip to main content

Python interface to JAGS for Bayesian analysis via MCMC

Project description

PyJAGS

From prior to posterior

CI PyPI Python License codecov

PyJAGS brings JAGS (Just Another Gibbs Sampler) to Python -- a mature, battle-tested engine for Bayesian inference via Markov Chain Monte Carlo, trusted by researchers in statistics, ecology, epidemiology, and finance for over two decades.

Why PyJAGS?

Instant models, no compilation. JAGS interprets the BUGS model language at runtime. Change a prior, re-run immediately. No C++ compiler, no minutes-long compilation step. From idea to posterior in seconds.

Models that gradient-based samplers cannot touch. Discrete parameters, mixture components, change-point models, latent class indicators -- JAGS samples them directly through Gibbs sampling. No marginalization tricks, no relaxation hacks, no divergence warnings.

Incremental sampling. JAGS retains chain state between sample() calls. Extending a run is a single line of code. Save your samples to HDF5, shut down, come back tomorrow, pick up exactly where you left off. No other Python Bayesian package makes this so natural.

The BUGS language. If you've used JAGS, WinBUGS, or OpenBUGS in R, your model files work unchanged. Decades of published BUGS models from textbooks, papers, and the vast BUGS/JAGS ecosystem are immediately available.

Information-theoretic diagnostics. With the optional Divergence package, PyJAGS offers diagnostics that go beyond R-hat and ESS: information gain (how much did the data teach us about each parameter?), chain divergence (are my chains truly sampling the same distribution?), Bayesian surprise (which observations are outliers?), and prior sensitivity analysis -- all computed directly from ArviZ inference data.

Lightweight and modern. Three core dependencies (numpy, arviz, h5py). Pre-built wheels for Linux and macOS. PEP 561 type stubs. 100% docstring coverage. 250 tests. CI on Python 3.12, 3.13, and 3.14.

Quick Start

import pyjags
import arviz as az

model_code = """
model {
    mu ~ dnorm(0, 0.001)
    sigma ~ dunif(0, 100)
    tau <- pow(sigma, -2)
    for (i in 1:N) { y[i] ~ dnorm(mu, tau) }
}
"""

model = pyjags.Model(code=model_code, data=dict(y=y, N=len(y)),
                     chains=4, adapt=1000, seed=42)
model.sample(1000, vars=[])                         # burn-in
samples = model.sample(5000, vars=["mu", "sigma"])   # production

idata = pyjags.from_pyjags(samples)
az.summary(idata)

Tutorials

The notebooks/ directory contains a series of tutorials that teach Bayesian inference through compelling real-world stories. Each notebook weaves historical context and narrative alongside working PyJAGS code.

Notebook The Story
The Reverend's Question Begin where it all began: Thomas Bayes' posthumous theorem (1763). Estimate a star's position, watch beliefs sharpen with evidence, and discover why Bayesian inference gives you not just answers but honest uncertainty.
The Paradox of Shrinkage In 1955, Charles Stein proved something nobody believed: estimating things separately is always worse than borrowing strength across groups. See the paradox come alive in the classic Eight Schools dataset.
The Wells of Bangladesh Three thousand families discovered their drinking water was poisoned. Their decision to switch wells -- driven by distance, arsenic levels, and education -- becomes a lesson in logistic regression with real human stakes.
The Hidden Cost of Every Trade Every stock trade carries a hidden cost that most investors never see. Use a latent variable model to reveal the bid-ask spread from daily prices -- and discover why JAGS's ability to sample discrete parameters is a structural advantage.
When It Rains, It Pours The 2008 financial crisis through the lens of stochastic volatility. Build a model with 1,260 latent variables, learn parallel sampling, HDF5 persistence, chain merging, and automatic convergence -- the full practitioner's toolkit.

Features

Core Sampling

  • Parallel chains across CPU cores (3-4x speedup)
  • Reproducible sampling via seed (numpy.random.SeedSequence)
  • Generator-based sampling with iter_sample() for live monitoring
  • Incremental sampling with sample_more() and sample_until()
  • Model syntax validation with check_model()

ArviZ Integration

  • from_pyjags() converts to ArviZ InferenceData with prior, observed data, constant data, log-likelihood, and warmup groups
  • loo() and compare() for model comparison via PSIS-LOO
  • summary() and dic_samples() for quick diagnostics

Advanced Diagnostics (via Divergence)

Install with pip install pyjags[diagnostics]:

from pyjags.diagnostics import information_gain, convergence_report

idata = pyjags.from_pyjags(posterior, prior=prior_samples)

ig = information_gain(idata)        # KL divergence: prior -> posterior
report = convergence_report(idata)  # R-hat + ESS + chain energy distance

Also available: bayesian_surprise(), model_divergence(), prior_sensitivity(), uncertainty_decomposition().

Persistence

  • Save and load MCMC samples via HDF5
  • Merge samples along iterations or across chains
  • PEP 561 py.typed and console.pyi type stubs

Who Is PyJAGS For?

Coming from R? Your BUGS model files work unchanged. You get the same JAGS engine with Python's data science ecosystem.

New to Bayesian statistics? Start with The Reverend's Question -- your first posterior in minutes, with historical context that makes the ideas unforgettable.

Bayesian veteran? PyJAGS complements HMC-based tools for models with discrete parameters, mixture components, and change-points. The Divergence integration gives you information-theoretic diagnostics that no other package provides.

Compatibility

Component Supported
Python 3.12+
NumPy 1.x and 2.x
ArviZ 1.0+
macOS Intel and Apple Silicon
Linux Debian/Ubuntu (tested), others (untested)

Getting Started

Option 1: Docker (fastest, any platform)

If you have Docker installed, PyJAGS includes a ready-to-run development environment with JAGS, Python, and Jupyter Lab pre-configured. No native JAGS installation needed:

git clone https://github.com/michaelnowotny/pyjags.git
cd pyjags
cp .env.example .env
./scripts/jagslab build   # build Docker image with JAGS + Python
./scripts/jagslab start   # launch Jupyter Lab at http://localhost:8888

The jagslab CLI manages everything:

Command What it does
./scripts/jagslab start Start Jupyter Lab (Docker)
./scripts/jagslab test Run the full test suite (250 tests)
./scripts/jagslab shell Open a bash shell in the container
./scripts/jagslab lab Start Jupyter Lab natively (no Docker)

Option 2: Native Installation (macOS / Linux)

For native installation, you need JAGS (the C++ engine) installed on your system and a properly configured Python environment.

We recommend uv for managing Python installations and virtual environments:

macOS (Apple Silicon):

# 1. Install JAGS via Homebrew
brew install jags

# 2. Set PKG_CONFIG_PATH (add to ~/.zprofile or ~/.zshrc)
export PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"

# 3. Set up Python environment with uv
curl -LsSf https://astral.sh/uv/install.sh | sh
uv python install 3.12
uv venv --python 3.12 .venv
source .venv/bin/activate

# 4. Install PyJAGS
uv pip install pyjags

# 5. Optional: advanced diagnostics via Divergence
uv pip install pyjags[diagnostics]

macOS (Intel):

brew install jags
pip install pyjags

Linux (Debian/Ubuntu):

sudo apt-get install jags pkg-config
pip install pyjags

Windows: Use WSL2 with Ubuntu, then follow the Linux instructions.

From Source (development)

git clone https://github.com/michaelnowotny/pyjags.git
cd pyjags
pip install -e ".[dev]"
pre-commit install

Ecosystem

PyJAGS is part of a growing ecosystem for Bayesian analysis in Python:

  • ArviZ -- the standard library for Bayesian diagnostics and visualization. PyJAGS integrates natively via from_pyjags().

  • Divergence -- a comprehensive information-theoretic toolkit providing 40+ measures of entropy, divergence, and distance (KL, Jensen-Shannon, Hellinger, total variation, chi-squared, Renyi, MMD, Wasserstein, energy distance, transfer entropy, Fisher divergence, kernel Stein discrepancy, and more). Through the pyjags.diagnostics module, Divergence provides Bayesian-specific analyses that are unique in the Python ecosystem:

    • Information gain: how many nats of information did the data contribute to each parameter? No other package answers this question.
    • Chain divergence: pairwise distributional comparison between MCMC chains using energy distance or MMD -- catches problems that R-hat misses because it compares entire distributions, not just moments.
    • Bayesian surprise: per-observation surprise scores that identify influential data points and outliers.
    • Prior sensitivity: quantify how much your conclusions depend on your prior choice, using any of 7 divergence measures.
    • Uncertainty decomposition: separate aleatoric (irreducible noise) from epistemic (parameter uncertainty) in your predictions.

    Install with pip install pyjags[diagnostics].

Troubleshooting

macOS: symbol not found '_JAGS_NA'

Verify pkg-config --libs --cflags jags succeeds. If not, set PKG_CONFIG_PATH as shown in the installation instructions.

macOS: architecture mismatch (x86_64 vs arm64)

Install JAGS via the ARM Homebrew at /opt/homebrew:

/opt/homebrew/bin/brew install jags
CMake errors during build
brew install cmake    # macOS
sudo apt install cmake  # Linux
pip install cmake     # anywhere

Links

Acknowledgements

License: GPLv2

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

pyjags-2.4.0.tar.gz (217.1 kB view details)

Uploaded Source

Built Distributions

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

pyjags-2.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (19.8 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pyjags-2.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (18.6 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

pyjags-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (19.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pyjags-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (18.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

pyjags-2.4.0-cp313-cp313-macosx_14_0_arm64.whl (10.4 MB view details)

Uploaded CPython 3.13macOS 14.0+ ARM64

pyjags-2.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (19.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pyjags-2.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (18.6 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

pyjags-2.4.0-cp312-cp312-macosx_14_0_arm64.whl (10.4 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

File details

Details for the file pyjags-2.4.0.tar.gz.

File metadata

  • Download URL: pyjags-2.4.0.tar.gz
  • Upload date:
  • Size: 217.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyjags-2.4.0.tar.gz
Algorithm Hash digest
SHA256 789d1767cedcc8edb44e76b694ce0cf04f7a3523aa1c28dcda1505f9b608d3e7
MD5 1c566863475f5aa543bf32f78088c5d4
BLAKE2b-256 84509c5e04cfe42a046b8ca031f442c9cbc02ea5016b5960f0080338db0517c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0.tar.gz:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjags-2.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyjags-2.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 390f4bb2c113043cfc98a2fac69212015204dd1ab4fa3214240e102385ae873c
MD5 f1a01c7c4dc6094fa69d33ae4db3af3f
BLAKE2b-256 8eb565b28b1a93482960e6b7006889febee4bcabe725b0262814a15fe86746ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjags-2.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pyjags-2.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 3ab2523a8275eb28eb1382874c02f18b45818752c0e322dc6ce2e6066a450b50
MD5 32d7e67d1e74c0f18f18ebd6993f269b
BLAKE2b-256 a74058ffb0f235f265e6ae3b2a7080a68de13c0c81bc8e362540522604209677

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjags-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyjags-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5fb70cf95eb6863039200b358fd7b56ad3bff6f34dc98ee5f073594286ab2779
MD5 c7f5a7cabe51f8aa367e5737642f3c03
BLAKE2b-256 1efb7159591b0a363ad43aad9a845fb3fac46fe6eb6700498b07d3adfd2ddb8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjags-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pyjags-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d1a9cd91eb69956d99a67f99345da76557805f2be0419828d1908dbf6d03a2d4
MD5 9424fb710ba4f7db0b2e855100d66b94
BLAKE2b-256 751aeadc4583bc671e25374bfa3117f82e52cde87901b399da504dc7ae8fe5c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjags-2.4.0-cp313-cp313-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pyjags-2.4.0-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 0ffc409dbe6e357e7aa4712126ee4d5b59ae4ff1a01622031f12e741de8e145b
MD5 51d032f3d17d6741e05992b3d486d9ee
BLAKE2b-256 311f1720f289e55cff0da7e9ce8591f29326abecc3a8bc5480c3877516c6c209

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0-cp313-cp313-macosx_14_0_arm64.whl:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjags-2.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyjags-2.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bdc905813934a6485cb53d8d2d3d9ce4ff5e36f167eb873ceb10c46d967df825
MD5 903096e35e39d294e90ffebb43089611
BLAKE2b-256 4dcb9960cd18d29a7f40eab099cc1e23ae24a7785123cacac06fe4309468f6b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjags-2.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pyjags-2.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 58a8fbb58639d146777d628f0edc7d5e09019a57913cb5c65bca4410ae854d35
MD5 7a06586cf339e95752736d272a65ff0e
BLAKE2b-256 a70db03bdb08ec4c354985b5bd498fe194e2fef1a55509426765782c5905f2e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjags-2.4.0-cp312-cp312-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pyjags-2.4.0-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 31ba703ff6be3e166eff8038b4f355ccde9063d5281e241ac0d8e2ff2bca0980
MD5 690c33fefc2562af3639530fe7395336
BLAKE2b-256 5e365983d943e9256afd94a64fd471486fce8d7248a33a67600c062114d78e45

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjags-2.4.0-cp312-cp312-macosx_14_0_arm64.whl:

Publisher: release.yml on michaelnowotny/pyjags

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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