Instructions for developers and contributors#

PyIBS implements inverse binomial sampling in Python. It requires Python 3.10 or later, NumPy 2.0 or later, and SciPy 1.13 or later. The reference implementation is ibslike.m in MATLAB IBS; the catalogue of deliberate differences lists the intentional differences and explains their reasons.

The published documentation is at https://acerbilab.org/pyibs/.

Installation instructions for developers#

For a source checkout with development dependencies:

  1. Clone the PyIBS GitHub repository:

    git clone https://github.com/acerbilab/pyibs
    cd pyibs
    
  2. Create a virtual environment with uv and install PyIBS in editable mode, so changes to the source take effect without reinstalling:

    uv venv --python 3.12 .venv
    uv pip install -e ".[dev]"
    
  3. Install the pre-commit hooks, which format and check staged files before a commit:

    .venv/bin/python -m pre_commit install
    

Commands on this page use the environment’s interpreter, .venv/bin/python. On Windows, replace this path with .venv\Scripts\python.exe, including in the hook-installation command above. No environment activation is needed. setuptools_scm derives PyIBS’s version from the Git tags.

Declare dependencies in pyproject.toml: runtime requirements under dependencies, test requirements under the test extra, and development requirements under dev. The development extra also includes the test requirements. Every runtime and test dependency needs a lower bound; CI tests the lowest permitted versions.

Coding conventions#

Useful background on Python style:

The repository conventions below keep contributions consistent with the existing code.

Code formatting#

The pre-commit hooks run Black at a line length of 79, isort with Black’s profile, and pycln. To check every file:

.venv/bin/python -m pre_commit run -a

Once installed, the hooks check staged files at each commit and may reformat them. Restage any modified files before committing again. The hooks are defined in .pre-commit-config.yaml and their formatting settings in pyproject.toml. CI does not check formatting, so run the hooks locally.

Docstrings#

The docstrings follow the NumPy format. Use the numpydoc example and the docstrings in pyibs/ibs.py as guides.

Random numbers#

Pass an explicit numpy.random.Generator to code that draws random numbers. A fixed seed must reproduce a run when the sampling schedule does not depend on timing.

Exceptions#

Use standard Python exceptions where appropriate.

Testing#

The pytest suite lives in pyibs/testing/. It ships with the package and can be run after installing the test extra with pytest --pyargs pyibs. From a development checkout, run the full default suite or a selected test with:

.venv/bin/python -m pytest
.venv/bin/python -m pytest pyibs/testing/test_sampler.py::test_cost

Test requirements:

  • Run the relevant tests before submitting a change. CI runs the full matrix on pull requests to main or dev* branches that change the package, examples, installation metadata, or test workflows. It covers Windows, Linux, and macOS with Python 3.10–3.14, plus Python 3.10 with the lowest NumPy, SciPy, and pytest versions allowed by pyproject.toml.

  • Seed every test that draws random numbers so its failure can be reproduced.

  • State statistical tolerances in standard errors, 4.5 by default. Investigate a failing statistical test; do not reseed it to make it pass.

  • Use a fake clock advanced by the simulator for timing tests, or make the expected values independent of the machine’s speed. Avoid timing margins that a slow runner can miss.

  • Some tests port the self-tests of ibslike.m, the reference implementation.

The integration tests in pyibs/testing/integration/ fit the example model with PyBADS or PyVBMC, using IBS estimates as the noisy target. The default checkout run excludes the integration marker. Each integration test skips when its package is absent or too old: it requires PyBADS 1.5.1 or later or PyVBMC 1.5 or later, respectively. These tests take a few minutes. To run them:

uv pip install "pybads>=1.5.1" "pyvbmc>=1.5.0"
.venv/bin/python -m pytest -m integration pyibs/testing/integration/test_pybads.py -s -v
.venv/bin/python -m pytest -m integration pyibs/testing/integration/test_pyvbmc.py -s -v

Code documentation#

Build the documentation with Sphinx. The source is in docsrc. From the repository root, with the environment’s bin directory (Scripts on Windows) first on the PATH:

PATH="$PWD/.venv/bin:$PATH" make -C docsrc github

The target copies the example notebooks into the documentation source, builds the site, copies it to the gitignored docs/ directory, and removes the temporary notebook copies. Open docs/index.html to view the result. On Windows, use .venv/Scripts in the PATH command above, or run .\make.bat github from docsrc in cmd with that directory on PATH. The build must produce no warnings.

If pages or navigation do not update correctly, clear the generated site in docs/ and the cached docsrc/_build directory, then rebuild:

make -C docsrc clean

On Windows, run .\make.bat clean from docsrc in cmd instead.

General structure#

Each public class or function needs a hand-written .rst page in docsrc/source/api/classes/ or docsrc/source/api/functions/. Give it a short introduction and an autoclass or autofunction directive to render the docstring, for example:

.. autoclass:: pyibs.IBS
   :members:

Add the page to its table of contents: documentation.rst for a headline page, and api/classes/classes.rst or api/functions/functions.rst. Keep the documentation in step with changes to the public API.

Examples#

The example notebooks live in examples/ and are installed as pyibs.examples. Their model is in psycho_model.py. The documentation renders saved outputs without executing the notebooks. To rerun them in place, with PyBADS, PyVBMC, matplotlib and ipykernel installed in the environment:

uv pip install nbconvert ipykernel matplotlib "pybads>=1.5.1" "pyvbmc>=1.5.0"
PATH="$PWD/.venv/bin:$PATH" make -C examples/scripts run

After rerunning the notebooks, regenerate their code in examples/scripts/ with make -B -C examples/scripts. Keep the environment first on PATH and install nbconvert, IPython, and the Black and isort versions specified by the pre-commit hooks. Edit the notebooks; the scripts are generated files.

git commits#

Commits follow the conventional commits style. See the cheat sheet for examples.

Use a feature branch for a contribution and submit completed changes with passing tests through a pull request. For example, replacing <new-feature> with your branch name:

git checkout -b <new-feature>
[... do stuff and commit ...]
git push -u origin <new-feature>
[... open a pull request on GitHub when ready ...]

See Feature Branch for background on this workflow.

Changelog#

In the same commit as a change to results, the interface, or what a script sees or has to handle, add one or two sentences for users under Unreleased in CHANGELOG.md. A change that can break a script written for the last release or alter its results also needs an entry in the opening “Upgrading from” list. When a change adds, removes, or alters an intentional difference from ibslike.m, update the corresponding entry in the catalogue.