Open-source project
dfm/emcee avatar
dfm/emcee

emcee ships one sampler and keeps its parallel backends out of coverage

The Python ensemble sampling toolkit for affine-invariant MCMC

1,605 stars447 forksPythonMIT

At a glance

What is it?
emcee is the Python implementation of the affine-invariant ensemble sampler behind much of the astrophysics literature, and its own configuration files are more informative than its README about what is tested, what is optional and what is legacy.
Who is it for?
Adopt emcee if your work is sampling a continuous posterior with an ensemble method and you want a package with a long publication record rather than one you have to validate yourself. Do not adopt it expecting nested sampling, Hamiltonian Monte Carlo or a built-in convergence criterion: the repository documents one sampler and its configuration files name the parallelism backends as legacy modules excluded from coverage.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • dfm/emcee1,605 ★ · +2
Star history
Repository2026-10-162026-11-07
dfm/emcee1.6k1.6k

2 Stars in the last 22 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

One sampler, one paper, one citation

emcee is described as a stable, well tested Python implementation of the affine-invariant ensemble sampler for Markov chain Monte Carlo, proposed by Goodman and Weare in 2010. The claim of stability is not marketing in the usual sense: the package classifier in setup.py says Development Status :: 5 - Production/Stable, and the README states the code has already been used in several published projects in the astrophysics literature.

The affine-invariance property is the reason to reach for it rather than a random-walk sampler. A stretch-move ensemble sampler treats a set of walkers that are jointly updated, and the update is invariant under affine transformations of the parameters. In practice that means a posterior with badly scaled or strongly correlated coordinates can still be sampled without the preconditioning you would otherwise have to hand-tune. The cost is that you must have more than one walker per dimension, which is a real constraint on how you configure a run.

The README asks you to cite Foreman-Mackey, Hogg, Lang and Goodman (2012) if you find the code useful, and supplies the BibTeX entry for it. The repository also carries a joss/ directory, which is the Journal of Open Source Software paper package, and AUTHORS.rst for credit.

The scope is narrow by design. This is a sampling library, not an inference framework: no posterior predictive machinery, no model comparison, no plotting. You get chains and you do your own analysis with whatever you already use.

The extras tell you what the library expects from the ecosystem

setup.py is where the dependency story is, and it is short.

python
INSTALL_REQUIRES = ["numpy"]

One required dependency. Everything else is opt-in through extras.

python
EXTRA_REQUIRE = {
    "extras": ["h5py", "scipy", "tqdm", "ipywidgets"],
    "tests": ["pytest", "pytest-cov", "coverage[toml]"],
}

Each of those four answers a question. The extras group names h5py, scipy, tqdm and ipywidgets.

The tests extra is pytest with coverage, and the coverage configuration in pyproject.toml runs in parallel mode with branch coverage over the emcee package.

The package layout is a src/ directory with find_packages(where="src"), and the version comes from setuptools_scm rather than a hard-coded string.

python
use_scm_version={
    "write_to": os.path.join(
        "src", NAME, "{0}_version.py".format(NAME)
    ),
    "write_to_template": '__version__ = "{version}"\n',
},

So the version is derived from git tags and written into a generated module. That is why there is no version literal in the file, and it is also why a build from a shallow or untagged checkout produces an unhelpful version rather than a failure.

Coverage config names the legacy parts, and that is the useful signal

The most revealing lines in pyproject.toml are the coverage exclusions.

toml
omit = [
    "emcee/interruptible_pool.py",
    "emcee/mpi_pool.py",
    "emcee/ptsampler.py",
    "docs/*",
    "tests/*",
    "*__init__*"
]

Three modules are deliberately not measured, and all three are about running walkers in parallel rather than about the sampler itself. interruptible_pool.py and mpi_pool.py are pool implementations, and ptsampler.py is the previous sampler interface kept for compatibility with code written against earlier versions.

The practical reading is that emcee's parallelism story is inherited rather than current. If your cluster work runs today, the pool module you would reach for is one the project does not count as tested, and the older entry point is likewise unmeasured. That is not a reason to avoid the package for single-process work, but it is a reason to check your parallel path against the code rather than against the coverage badge.

The exclusion list in the report section is more revealing about intent than about mechanics. Lines to skip include raise NotImplementedError, except ImportError, logging.warning, and, notably, the strings deprecation_warning and deprecated.

toml
exclude_lines = [
    "pragma: no cover",
    "raise NotImplementedError",
    "raise ImportError",
    "except ImportError",
    "logging.warning",
    "deprecated"
]

A project that excludes deprecated code from coverage is telling you the codebase still contains deprecated paths, which matches ptsampler.py sitting alongside the current interface.

Formatting rules that tell you the era of the code

The tooling configuration is small and reveals a lot.

toml
[tool.black]
line-length = 79

[tool.isort]
line_length = 79
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
known_third_party = ["h5py", "matplotlib", "numpy", "pkg_resources", "pytest", "setuptools"]

A line length of 79 rather than black's default 88 is the give-away: this project predates the current default and has deliberately kept the older limit. The isort settings with multi_line_output 3 and a trailing comma are the vertical-hanging-indent style that was standard in that period, and known_third_party names matplotlib, which is not listed in the package's install requirements.

Around that there is a.pre-commit-config.yaml at the root, tox.ini for multi-environment test runs, and a.readthedocs.yaml for the documentation build. Those three together describe a project that runs its formatting on commit rather than after review.

The repository also has a VISION.md, which is unusual and worth reading if you are deciding whether to depend on it, because it is where a maintainer states intent rather than shipping instructions. HISTORY.rst is the changelog, and it is the file to read when you are deciding what version to pin.

What it is not, and where the alternatives start

emcee samples. That is the boundary, and it is a boundary several other libraries sit on the other side of.

If you need nested sampling, which handles multimodal posteriors and gives you an evidence value, a nested sampler is the right tool and emcee will not become one. If your posterior is differentiable and you have gradients, Hamiltonian Monte Carlo methods move through the space far more efficiently per sample, at the cost of needing a differentiable log-probability and a tuning step for step size. If your parameters include discrete components, an ensemble stretch move is not the right structure at all, because the affine-invariance argument assumes continuous coordinates.

Within continuous sampling, the real competitor is the alternative affine-invariant implementation that also runs ensembles of walkers. The practical difference is not algorithmic; the algorithm is Goodman and Weare. It is maintenance, packaging and how much you trust the interfaces around it, which is why the classifier and the coverage configuration are worth reading before you choose.

There is also the deployment question. Because the version is derived from git, installing from a source archive without tags gives you an odd version string, and a private mirror with the tags stripped behaves the same way. Pin to a released version rather than a branch.

Editorial conclusion

Adopt emcee if your work is sampling a continuous posterior with an ensemble method and you want a package with a long publication record rather than one you have to validate yourself. Do not adopt it expecting nested sampling, Hamiltonian Monte Carlo or a built-in convergence criterion: the repository documents one sampler and its configuration files name the parallelism backends as legacy modules excluded from coverage. Verify first that your parameters are continuous, since affine invariance is the property that lets you rescale a badly conditioned posterior, and read HISTORY.rst before pinning, because the newest tag is v3.1.6 from 2024-04-19 while the last push was on 2026-10-12, which means development has continued without a release. MIT licensing permits vendoring subject to its license conditions.

Frequently asked questions

What does emcee require to install?

The only required dependency is numpy. h5py, scipy, tqdm and ipywidgets are available through the extras group. pytest and coverage are in the tests extra.

How does emcee determine its version number?

The version comes from setuptools_scm and is written into a generated module under src. That means the version is derived from git tags rather than declared in setup.py, so an untagged or shallow checkout produces an unusual version.

Which parts of emcee are excluded from test coverage?

The coverage configuration omits emcee/interruptible_pool.py, emcee/mpi_pool.py and emcee/ptsampler.py, along with docs, tests and package init files. Those three modules are the parallel execution pools and the previous sampler interface.

Which paper should I cite for emcee?

The README asks you to cite Foreman-Mackey, Hogg, Lang and Goodman (2012), and provides the BibTeX entry for it. The sampler itself is the affine-invariant ensemble method proposed by Goodman and Weare in 2010.

Is emcee suitable for discrete parameters?

The package implements the affine-invariant ensemble sampler, whose advantage is invariance under affine transformations of continuous parameters, and the README notes it has been used in published astrophysics work. It is an ensemble sampler, not a nested or discrete sampler.

Official sources

  1. dfm/emcee on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dfm-emcee.svg)](https://hysenlabs.com/projects/dfm-emcee)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/dfm-emcee.svg)](https://hysenlabs.com/projects/dfm-emcee)

Was this useful?