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
26 changes: 7 additions & 19 deletions .github/actions/setup-pybnf/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ description: >-

inputs:
python-version:
description: Python version for the venv (e.g. "3.11", "3.12").
description: Python version for the venv (e.g. "3.12", "3.13").
required: true
bngsim:
description: >-
Expand All @@ -36,24 +36,14 @@ inputs:
[jax] extra.
required: false
default: 'false'
petab-spec:
description: >-
The petab requirement to install. Defaults to stock PyPI petab. A CI leg
overrides it with upstream libpetab-python main
(git+…/PEtab-dev/libpetab-python@main), where the native BnglModel loader
landed (PEtab-dev/libpetab-python#508), so the exporter oracle validates
`language: bngl` problems through petab's OWN native loader rather than the
register_bngl() monkeypatch (ADR-0026).
required: false
default: 'petab>=0.8,<1'
cache-suffix:
description: >-
uv cache namespace suffix. Two jobs that run the SAME python version
through this action share one content-addressed cache key (os/arch/python/
pyproject hash + this suffix) and race to save it -- a benign "another job
may be creating this cache" warning. Override per job to give each its own
namespace (e.g. the native-BNGL leg also runs 3.12, colliding with the
matrix 3.12 job under a shared suffix).
namespace (e.g. the jax leg also runs 3.12, colliding with the matrix
3.12 job under a shared suffix).
required: false
default: 'pybnf'

Expand Down Expand Up @@ -101,7 +91,6 @@ runs:
env:
BNGSIM: ${{ inputs.bngsim }}
JAX: ${{ inputs.jax }}
PETAB_SPEC: ${{ inputs.petab-spec }}
run: |
# Build the venv from the setup-python interpreter (see note above), not
# a uv-managed one.
Expand Down Expand Up @@ -141,10 +130,9 @@ runs:
# BNG2.pl is installed above, so model-level validation runs here too) AND
# the runtime math translator backing the expression observableFormula
# path (pybnf[petab], ADR-0035, petab.v2.math); stock PyPI petab carries
# the math grammar, so one install covers both. The exact petab
# requirement is the `petab-spec` input (default stock PyPI; a CI leg
# overrides it with upstream libpetab-python main to run the NATIVE BNGL
# loader, PEtab-dev/libpetab-python#508).
# the math grammar, so one install covers both. petab >= 0.9.0 ships the
# native `language: bngl` loader (PEtab-dev/libpetab-python#508), which
# is what the oracle loads BNGL problems through (#591).
# arviz/h5netcdf/h5py unskip the ArviZ InferenceData bridge oracle
# (ADR-0055; tests/test_inference_data.py + the tutorial diagnostics beat)
# and matplotlib unskips the profile-likelihood plot oracle (#467). These
Expand Down Expand Up @@ -174,7 +162,7 @@ runs:
'h5netcdf>=1' \
'h5py' \
'matplotlib>=3.5' \
"$PETAB_SPEC"
'petab>=0.9,<1'
# Install pybnf itself without re-resolving deps: on a bngsim: 'false'
# leg a re-resolve would pull bngsim in through pyproject.toml and
# defeat the point, and everywhere it would re-derive a dependency set
Expand Down
56 changes: 5 additions & 51 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ jobs:
strategy:
fail-fast: false
matrix:
# Every supported version (requires-python >= 3.11; classifiers list
# Every supported version (requires-python >= 3.12; classifiers list
# through 3.14). CI is free on this public repo, so we test each claimed
# version rather than just the endpoints.
# version rather than just the endpoints. 3.11 left with the petab 0.9
# floor (#591): petab 0.9.0 requires >= 3.12.
include:
- python-version: '3.11'
- python-version: '3.12'
- python-version: '3.13'
# bngsim publishes cp310-cp313 wheels, so 3.14 would fall back to
Expand All @@ -37,7 +37,7 @@ jobs:
bngsim: ${{ matrix.no-bngsim == '1' && 'false' || 'true' }}

- name: Warm the arviz version-check stamp
# arviz < 1.0 (the py<3.12 resolution) prints a daily refactor warning on import and
# arviz < 1.0 prints a daily refactor warning on import and
# records the date through a helper it calls atomic, which it is not: the temp file has
# a FIXED name, `daily_warning.tmp`, so every process shares it.
#
Expand Down Expand Up @@ -84,52 +84,6 @@ jobs:
# pull bngsim right back in).
run: uv run --no-sync pytest -m "not slow and not recovery" -n auto

# The PEtab v2 export oracle (ADR-0025/0026) validates emitted `language: bngl`
# problems at MODEL level. On the pytest job above (stock PyPI petab) that runs
# through the register_bngl() monkeypatch. This job installs upstream
# libpetab-python main instead -- where the native BnglModel loader landed
# (PEtab-dev/libpetab-python#508) -- so Problem.from_yaml loads BNGL through
# petab's OWN native loader, exercising the collapse-to-no-op path that
# otherwise only ever SKIPS and keeping us green against the merged upstream
# contribution ahead of its first PyPI release (0.8.2 does not yet carry it).
# One Python version is enough; the loader is pure Python.
pytest-native-bngl:
runs-on: ubuntu-latest
name: pytest (native BNGL loader)
steps:
- uses: actions/checkout@v6

- uses: ./.github/actions/setup-pybnf
with:
python-version: '3.12'
# This leg is about petab's loader, not simulation: the two oracle
# files it runs are backend-free, so skip the bngsim install (and run
# under PYBNF_NO_BNGSIM=1 below) rather than pay for a wheel nothing
# here exercises. The matrix legs above cover bngsim.
bngsim: 'false'
petab-spec: 'petab @ git+https://github.com/PEtab-dev/libpetab-python.git@main'
# This job also runs 3.12 through setup-pybnf, so without its own
# suffix it shares the matrix py3.12 job's cache key and one save loses
# the reservation (the "another job may be creating this cache"
# warning). Give it a distinct namespace.
cache-suffix: pybnf-native

# Fail loudly if the upstream build did not actually install (e.g. a
# resolution fallback to stock petab): the native path would silently skip
# otherwise.
- name: Assert petab has native BNGL support
run: |
uv run --no-sync python -c "import petab.v1.models as m; assert 'bngl' in m.known_model_types, 'upstream libpetab-python main is not installed: bngl is not a known petab model type'; print('native BNGL loader present')"

- name: Run the PEtab oracle through the native loader
env:
PYBNF_NO_BNGSIM: '1'
# The export + import oracles both drive Problem.from_yaml, which loads
# `language: bngl` through petab's own native BnglModel here (the
# register_bngl() monkeypatch collapses to a no-op). This is where the
# TestRegisterBngl native-no-op test actually runs instead of skipping.
run: uv run --no-sync pytest -m "not slow and not recovery" tests/test_petab_export.py tests/test_petab_import.py

# The gradient path (ADR-0059): the HMC reference sampler and the jax-gated
# gradient-assembly tests need the optional pybnf[jax] extra (jax + jaxlib +
# blackjax). jaxlib is a large install relative to the rest of the dep set, so
Expand All @@ -155,7 +109,7 @@ jobs:
jax: 'true'
# This job also runs 3.12 through setup-pybnf, so give it its own cache
# namespace to avoid racing the matrix py3.12 job's save (see the
# cache-suffix input / the native-BNGL job above).
# cache-suffix input).
cache-suffix: pybnf-jax

- name: Run the HMC + jax gradient tests
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to PyBNF are documented below. This project adheres to

## [Unreleased]

### Changed
- **PyBNF requires Python 3.12 or newer, and the `petab` extra requires petab 0.9 or
newer (#591).** petab 0.9.0 is the first release that loads a `language: bngl` model
natively, through the `BnglModel` loader PyBNF contributed upstream
(PEtab-dev/libpetab-python#508), and it requires Python 3.12. Python 3.11 support is
dropped with it.

### Removed
- **The `pybnf.petab.bngl_model` module, its `BnglModel` adapter, and the
`register_bngl()` shim that taught older petab releases to load BNGL models (#591).**
petab now does this itself, so PEtab's own validator checks a BNGL-model problem with no
PyBNF code involved; `register_bngl()` had already collapsed to a no-op on petab 0.9.0.
The stand-alone BNGL reader and the parameter-expression evaluator (#666) stay: the
importer and exporter use the reader, and the evaluator is the staging copy for an
upstream port, since petab's native loader does not yet evaluate an expression-valued
parameter.

### Added
- **A stochastic fit now confirms its best fit by running the top parameter sets again
(#659).** When a model is stochastic, running it twice with the same parameter values
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ For documentation, refer to the online documentation at <https://lanl.github.io/

## Installation

PyBNF requires Python 3.11 or higher.
PyBNF requires Python 3.12 or higher.

```bash
python3 -m pip install pybnf
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,29 @@ and the neutral-seam discipline reused for `_bngl.parse_model`). Issues: **#420*
**#407** (umbrella), upstream **PEtab-dev/PEtab#436** (Step B target / spec). Follow-ups: Step B
(`libpetab-python` PR mirroring `PySBModel`); conditions/experiments + dose-response export (which
will exercise `get_valid_ids_for_condition_table` / `is_state_variable` for real).

## Addendum (2026-09-10): the adapter and `register_bngl()` are retired; petab 0.9.0 ships the loader (issue #591)

**Accepted and implemented 2026-09-10.** Step B landed: the pybnf-free port of `BnglModel`
merged into `libpetab-python` (PEtab-dev/libpetab-python#508) and shipped in petab 0.9.0 on
2026-09-07, whose `known_model_types` is `{sbml, bngl, pysb}`. The "collapse to a no-op" this
ADR anticipated had therefore already happened on every 0.9.0 installation: `register_bngl()`
saw `bngl` registered and returned without rebinding, and `Problem.from_yaml` loaded BNGL
through petab's own class. #591 removes what that left behind: `pybnf/petab/bngl_model.py`
(the adapter, `register_bngl()`, and its `_locate_bng2` helper), the dedicated CI leg that
installed upstream `main` to reach the native loader ahead of a release, the `petab-spec`
input of the setup action that leg used, and every test and lesson that called the shim. The
`petab` and `tests` extras now floor at `petab >= 0.9`, which floors the project at Python 3.12
(petab 0.9.0 requires it), so the 3.11 matrix leg and classifier go with it.

**What stays, and one gap the retirement exposes.** `_bngl.parse_model` stays: it is the
reader the importer and exporter use, and the upstream twin's drift note now points at the
shipped module rather than a branch. `_bngl_expr` (#666, the parameter-expression evaluator)
also stays, though its only consumer was the adapter: petab's native `BnglModel` does not
evaluate an expression-valued parameter (`get_parameter_value` raises `NotImplementedError`,
`get_free_parameter_ids_with_values` skips it), which is the pre-#666 behaviour on the
petab-side validation path. That is not a regression of this change, since the no-op already
routed 0.9.0 users to the native class, but it is the next upstream port, and the evaluator is
kept as its staging copy. `TestNativeBnglModel` in `tests/test_petab_export.py` pins the ABC
seam the exporter relies on against petab's class and asserts the native loader is present, in
place of the retired adapter unit tests and the CI leg's assert step.
8 changes: 4 additions & 4 deletions docs/cluster.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Running on a cluster

PyBNF is designed to run on computing clusters that utilize a shared network filesystem. PyBNF comes with built-in support for clusters running Slurm. It may also be manually configured to run on clusters with other managers (Torque, PBS, etc.).

Installation of PyBNF on a cluster has the same requirements as installation on a workstation, namely Python 3.11 or higher with the pip package manager. This is available on many clusters,
but may require loading a module to access. In Slurm, you can view the available modules with the command ``module avail``, and load the appropriate one with ``module load [modulename]``. Once Python 3.11 or higher and pip are loaded, the same :ref:`installation instructions <installation>` apply as for a standard installation.
Installation of PyBNF on a cluster has the same requirements as installation on a workstation, namely Python 3.12 or higher with the pip package manager. This is available on many clusters,
but may require loading a module to access. In Slurm, you can view the available modules with the command ``module avail``, and load the appropriate one with ``module load [modulename]``. Once Python 3.12 or higher and pip are loaded, the same :ref:`installation instructions <installation>` apply as for a standard installation.
Assistance from the cluster administrators may be helpful if any cluster-specific issues arise during installation.


Expand Down Expand Up @@ -104,8 +104,8 @@ An example batch script -- ``examples/tcr/tcr_batch.sh`` with a single word chan
#SBATCH --job-name=pybnf

# EDIT THIS LINE for your cluster: load a module (or activate a virtual
# environment) that provides Python 3.11 or newer with PyBNF installed.
module load python/3.11
# environment) that provides Python 3.12 or newer with PyBNF installed.
module load python/3.12

pybnf -c tcr-ss.conf -t slurm-srun -o

Expand Down
12 changes: 6 additions & 6 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ PyBNF can also be installed on Windows, but functionality on Windows has been le
Python
------

PyBNF requires an installation of Python version 3.11 or higher.
PyBNF requires an installation of Python version 3.12 or higher.
This requirement is declared in the package metadata, so installers such as ``pip`` and ``uv`` will refuse to install PyBNF into unsupported Python environments with a clear Python-version error.

Linux and Mac
^^^^^^^^^^^^^

Python 3 comes built-in on many new Linux and Mac operating systems.
To check if you have a supported Python 3, run the command ``python3 --version``. This will print
the version number, or will give an error if you don't have Python 3. Confirm that the version is 3.11 or higher.
the version number, or will give an error if you don't have Python 3. Confirm that the version is 3.12 or higher.

Also confirm that your Python 3 has the ``pip`` package manager, which is used to install PyBNF. Run the command ``python3 -m pip``. This will give a help message if you have pip, or an error if not.

If you are missing python3 or pip, an easy way to get them is by installing the `Anaconda`_ Python distribution for Python v3.11 or higher.
If you are missing python3 or pip, an easy way to get them is by installing the `Anaconda`_ Python distribution for Python v3.12 or higher.
Instructions for installing on various platforms can be found on the `Anaconda`_ website.

.. _windows_install:
Expand All @@ -34,7 +34,7 @@ Windows

Windows does not come with built-in Python, so it must be installed separately. Additionally, if :ref:`BioNetGen <bng_install>` will be used, Perl installation is required in the same environment as the python installation (i.e., the commands ``python`` and ``perl`` must both work on the same command line).

Our recommended configuration consists of installing `Strawberry Perl`_ and `Anaconda`_ Python 3.11 or higher. The Windows distribution of Anaconda includes the application "Anaconda Prompt", which provides a command line. This is the command line that you should use whenever this documentation refers to the command line or terminal. After installing both Anaconda and Strawberry Perl, a system restart may be required for Anaconda Prompt to find the Perl installation.
Our recommended configuration consists of installing `Strawberry Perl`_ and `Anaconda`_ Python 3.12 or higher. The Windows distribution of Anaconda includes the application "Anaconda Prompt", which provides a command line. This is the command line that you should use whenever this documentation refers to the command line or terminal. After installing both Anaconda and Strawberry Perl, a system restart may be required for Anaconda Prompt to find the Perl installation.

For troubleshooting, or more advanced configuration, note that the requirement is to have both Python 3 and Perl on the current path. The current path can be checked with the command ``echo %PATH%`` and set (temporarily) with the command ``set PATH=[newpath]``, where ``[newpath]`` is a semicolon-delimited list of directories to search.

Expand All @@ -54,7 +54,7 @@ Simply type the following in a terminal:
Windows users running Anaconda Python 3 from "Anaconda Prompt" should instead type only ``pip install pybnf``.

The above command will use your current version of Python 3 to install the most recent version of PyBNF released on the Python Package Index, along with all required dependencies.
If your Python version is older than 3.11, ``pip`` will stop before installation and report that PyBNF requires Python 3.11 or higher.
If your Python version is older than 3.12, ``pip`` will stop before installation and report that PyBNF requires Python 3.12 or higher.

Depending on your Python configuration, the above command may require root access and install PyBNF for all users on the computer. If you don't want to do this, you may add the flag ``--user`` to the end of the command, to install without root access for only the current user.

Expand All @@ -71,7 +71,7 @@ To run PyBNF once without keeping a tool installation, use:

:command:`uvx pybnf --help`

As with ``pip``, ``uv`` will select a Python version compatible with PyBNF or report that Python 3.11 or higher is required.
As with ``pip``, ``uv`` will select a Python version compatible with PyBNF or report that Python 3.12 or higher is required.

Installing from source
^^^^^^^^^^^^^^^^^^^^^^
Expand Down
6 changes: 0 additions & 6 deletions docs/modules/petab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ Measurement formulas
.. automodule:: pybnf.petab.formula
:members:

BNGL model loader
==============================

.. automodule:: pybnf.petab.bngl_model
:members:

Importing a problem
==============================

Expand Down
31 changes: 17 additions & 14 deletions docs/petab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,23 @@ free parameters, priors, noise models, and data.
The BNGL model loader
---------------------

Stock libpetab ships only ``sbml`` and ``pysb`` model loaders, so on its own it
cannot load — or lint — a problem whose model is BNGL.
``pybnf.petab.register_bngl()`` teaches a running ``petab`` to load
``language: bngl`` models. It is idempotent and additive: it routes ``bngl`` to
PyBNF's loader and delegates every other language to the original, leaving
``sbml``/``pysb`` untouched. ``import_job`` and ``export_job`` arrange this for
you; call it yourself only when driving the ``petab`` library directly::

from pybnf.petab import register_bngl

register_bngl()

With the loader installed, PEtab's own validator (``petab.v2.lint`` /
``petablint``) can check a BNGL-model problem — see the lint-clinic lesson below.
``petab`` (libpetab-python) loads ``language: bngl`` models natively since 0.9.0,
through the ``BnglModel`` loader PyBNF contributed upstream
(PEtab-dev/libpetab-python#508). PEtab's own validator (``petab.v2.lint`` /
``petablint``) therefore checks a BNGL-model problem with no PyBNF code
involved::

from petab.v2 import Problem
from petab.v2.lint import lint_problem

report = lint_problem(Problem.from_yaml("petab/problem.yaml"))

The model-level check shells out to ``BNG2.pl --check`` when a BioNetGen is on
``BNGPATH`` or ``PATH`` and degrades to "valid" when none is, so validation never
falsely fails for lack of a backend. The ``register_bngl()`` shim that taught
older petab releases the same loader was retired together with the
``petab >= 0.9`` floor of the ``pybnf[petab]`` extra. See the lint-clinic lesson
below.

What round-trips
----------------
Expand Down
Loading
Loading