Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,15 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
- uses: astral-sh/setup-uv@v6
with:
python-version: '3.14'
enable-cache: true
- name: Install pandoc
run: sudo apt-get install -y pandoc
- name: Install Python dependencies
run: |
python -m pip install uv
uv pip install --system -e ".[docs]"
run: uv sync --extra docs --no-default-groups --frozen
- name: Build documentation
run: python -m sphinx.cmd.build docs doc_build -j2
run: uv run python -m sphinx.cmd.build docs doc_build -j2
- name: Deploy to atomicateam/docs
uses: JamesIves/github-pages-deploy-action@v4
with:
Expand All @@ -58,21 +56,19 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
- uses: astral-sh/setup-uv@v6
if: github.event.action != 'closed'
with:
python-version: '3.14'
enable-cache: true
- name: Install pandoc
if: github.event.action != 'closed'
run: sudo apt-get install -y pandoc
- name: Install Python dependencies
if: github.event.action != 'closed'
run: |
python -m pip install uv
uv pip install --system -e ".[docs]"
run: uv sync --extra docs --no-default-groups --frozen
- name: Build documentation
if: github.event.action != 'closed'
run: python -m sphinx.cmd.build docs doc_build -j2
run: uv run python -m sphinx.cmd.build docs doc_build -j2
- name: Deploy / update / remove preview
uses: rossjrw/pr-preview-action@v1
with:
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Publish
# Publish to PyPI whenever main is updated (any push, not only PR merges),
# but only after the full test suite passes

on:
push:
branches: [main]

permissions:
contents: read
checks: write
pull-requests: write

jobs:

# Run pre-deployment tests
test:
uses: ./.github/workflows/tests.yml

# Build
build:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
- name: Build sdist and wheel
run: uv build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/

# Publish
publish:
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/atomica
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
# main can be pushed without a version bump; skip instead of failing when the version already exists on PyPI
skip-existing: true
54 changes: 54 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Tests

on:
workflow_dispatch:
pull_request:
workflow_call:

permissions:
contents: read
checks: write
pull-requests: write

jobs:
test:
name: Tests (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true

# Python version comes from .python-version (read automatically by uv)
- name: Install dependencies
run: uv sync --extra test --no-default-groups --frozen

# pytest config (junit, coverage, -n 2) lives in pytest.ini; these flags
# add the notebook (nbval) validation on top
- name: Run tests
run: uv run pytest --nbval-lax --current-env --nbval-cell-timeout=600 --dist loadscope --durations=25

- name: Publish test results
uses: mikepenz/action-junit-report@v6
if: always()
with:
report_paths: junit/test-results.xml

# Surface coverage in the Actions run summary (no PR comment) using
# coverage.py's own markdown output - no third-party action needed. Only
# once (Linux); coverage is the same across the OS matrix.
- name: Coverage summary
if: always() && matrix.os == 'ubuntu-latest'
continue-on-error: true
shell: bash
run: |
echo "## Coverage" >> "$GITHUB_STEP_SUMMARY"
uv run coverage report --format=markdown >> "$GITHUB_STEP_SUMMARY"
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ target/
.ipynb_checkpoints

# pyenv
.python-version
# .python-version is intentionally tracked to pin the Python version for uv

# celery beat schedule file
celerybeat-schedule
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
79 changes: 44 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,97 +1,106 @@
# Atomica

[![Build Status](https://dev.azure.com/AtomicaTeam/Atomica/_apis/build/status/atomicateam.atomica?branchName=master)](https://dev.azure.com/AtomicaTeam/Atomica/_build/latest?definitionId=1&branchName=master)

[![PyPi version](https://badgen.net/pypi/v/atomica/)](https://pypi.org/project/atomica)
[![Tests](https://github.com/atomicateam/atomica/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/atomicateam/atomica/actions/workflows/tests.yml)

Atomica is a simulation engine for compartmental models. It can be used to simulate disease epidemics, health care cascades, and many other things.

For detailed documentation, visit [https://atomica.tools/docs](https://atomica.tools/docs)

## Installation

Atomica requires Python 3.10 or later and is distributed via PyPI. To install, run
Atomica requires Python 3.11 or later and is distributed via PyPI. To install, run

```
pip install atomica
```

## Git installation

If you want to install a different branch of Atomica, or plan to make changes to the Atomica source code, you will need to install Atomica via Git rather than via PyPI. This can be performed using
Atomica is mainly used as the modelling platform for downstream analyses. Therefore, the most common usage is to set up an analysis-specific repository, and simply include `atomica` as a dependency that will be installed automatically via PyPI. We recommend using [uv](https://docs.astral.sh/uv/) to manage Python environments, in which case `atomica` can be added as a dependency using

```
git clone https://github.com/atomicateam/atomica.git
cd atomica
pip install -e .
uv add atomica
```

## Running tests
## Claude Code integration

Atomica includes a suite of tests, some of which get automatically run and others that are used manually. The automated test suite can be executed with `pytest`, and can be run from within an isolated environment using `tox`. To use the tests, you will need to follow the steps above to perform a 'Git installation' because the tests are not included in the PyPI distribution. After installation, you can run individual test scripts from the `tests` directory with commands like:
Atomica ships an MCP server (`atomica.mcp`) that exposes tools for querying framework and databook files and a set of built-in workflow skills (MCP prompts). The tools let Claude read compartments, parameters, transitions, and variable metadata directly from `.xlsx` framework files, as well as read and write data in `.xlsx` databook files. The skills guide Claude through multi-step workflows such as producing a structured summary of a framework.

To register the server with Claude Code, run the following from within your project directory:

```
python tests/testworkflow.py
claude mcp add atomica -- uv run python -m atomica.mcp
```

Note that many of the tests open `matplotlib` figures as part of the test. If the test script is run on a machine without a display available, the error
Once added, the tools and skills are available automatically in any Claude Code session for that project. If you use Atomica across multiple projects and want the MCP server available in all of them without repeating the `claude mcp add` step, register it at the user level instead:

```
_tkinter.TclError: couldn't connect to display "localhost:0.0"
claude mcp add -s user atomica -- uv run python -m atomica.mcp
```

will be raised. In that case, simply set the `matplotlib` backend to `agg` which allows the calls to succeed with a display present. For example, run
The Atomica MCP will then be used whenever you are working within a project that has `atomica` as a dependency.

```
export MPLBACKEND=agg
python tests/testworkflow.py
```
## Advanced usage

### Using a branch in a downstream project

To run the automated suite, install the test dependencies using
To use an Atomica branch in a downstream project with `uv`, you can add the Git repository directly as a dependency

```
pip install -e ".[test]"
uv add git+https://github.com/atomicateam/atomica --branch <branch name>
```

which will install the additional development dependencies. Then, to run the automated suite, from the root directory (the one containing `README.md`) run:
For more information on this usage, see https://docs.astral.sh/uv/concepts/projects/dependencies/.

### Developer installation

If you want to install a different branch of Atomica, or plan to make changes to the Atomica source code, you will need to install Atomica via Git rather than via PyPI.

```
pytest
git clone https://github.com/atomicateam/atomica.git
cd atomica
pip install -e .
```

To run the tests in an isolated virtual environment, from the root directory, run
If using `uv`, simply cloning the repository is sufficient, and scripts can be run with `uv run`. If you are developing Atomica in parallel with your own analysis repository, it would be recommended to clone `atomica` and then install it in your analysis repository as an editable package with `uv`

```
tox
uv add --editable ../<path to atomica>
```

If you don't have `tox`, install it using `pip install tox`. To test against a specific Python version, pass it as an argument, e.g.
In which case you can edit your local copy of Atomica and have it reflected in your analysis code.

### Running tests

Atomica includes a suite of tests. The automated test suite can be executed with `pytest`.

```
tox -e py312
uv run --extra test pytest
```

## Claude Code integration
Note the inclusion of the extra `test` dependencies that are not installed by default. Many of the tests open `matplotlib` figures as part of the test. If the test script is run on a machine without a display available, the error

Atomica ships an MCP server (`atomica.mcp`) that exposes tools for querying framework and databook files and a set of built-in workflow skills (MCP prompts). The tools let Claude read compartments, parameters, transitions, and variable metadata directly from `.xlsx` framework files, as well as read and write data in `.xlsx` databook files. The skills guide Claude through multi-step workflows such as producing a structured summary of a framework.
```
_tkinter.TclError: couldn't connect to display "localhost:0.0"
```

To register the server with Claude Code, run the following from within your project directory:
will be raised. In that case, simply set the `matplotlib` backend to `agg` which allows the calls to succeed with a display present. For example, run

```
claude mcp add atomica -- uv run python -m atomica.mcp
export MPLBACKEND=agg
uv run --extra test pytest
```

Once added, the tools and skills are available automatically in any Claude Code session for that project. If you use Atomica across multiple projects and want the MCP server available in all of them without repeating the `claude mcp add` step, register it at the user level instead:
To also validate the example and tutorial notebooks, include the `nbval` options:

```
claude mcp add -s user atomica -- uv run python -m atomica.mcp
uv run --extra test pytest --nbval-lax --current-env --nbval-cell-timeout=600 --dist loadscope
```

The Atomica MCP will then be used whenever you are working within a project that has `atomica` as a dependency.
This will reproduce the automated testing that is executed on GitHub as part of the CI workflow.

### Adding custom skills

Skills are plain Markdown files in `atomica/mcp/skills/`. To add a new workflow, drop a `.md` file into that directory — it is registered as an MCP prompt automatically when the server starts, with no code changes required. The first `# Heading` line becomes the prompt description shown in the MCP client.
The MCP server publishes a set of skills, which are plain Markdown files in `atomica/mcp/skills/`. To add a new workflow, add a `.md` file into that directory — it is registered as an MCP prompt automatically when the server starts, with no code changes required. The first `# Heading` line becomes the prompt description shown in the MCP client.

## Troubleshooting

Expand Down
4 changes: 2 additions & 2 deletions atomica/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

Standard location for module version number and date.
"""
version = "1.32.3"
versiondate = "2026-08-27"
version = "1.32.4"
versiondate = "2026-09-01"
72 changes: 0 additions & 72 deletions azure-pipelines.yml

This file was deleted.

Loading
Loading