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
46 changes: 46 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Tests & checks

on:
pull_request:
workflow_dispatch: # allow running manually from the Actions tab

# cancel previous runs on a new commit
concurrency:
group: ${{ github.head_ref }}
cancel-in-progress: true

jobs:
ci:
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12", "3.13", "3.14"]
os: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repo
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v5

- uses: actions/cache@v4
name: Cache venv
with:
path: ./.venv
key: ${{ matrix.os }}-venv-${{ matrix.python-version }}-${{ hashFiles('**/uv.lock') }}

- name: Install the project dependencies
run: uv sync --group test --python "$(python -c 'import sys; print(sys.executable)')"
shell: bash

- name: Check pre-commit
run: uv run pre-commit run --all-files

- name: Run tests with pytest
run: uv run make test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ dist/
wheels/
*.egg-info

# Dev cache
.ruff_cache/

# Virtual environments
.venv

Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ setup: ## Install development dependencies
uv sync --group dev
uv run pre-commit install

test:
uv run ruff check

help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
8 changes: 4 additions & 4 deletions bbttest/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""bbt-test: Bayesian Bradley-Terry model for algorithm comparison."""

from .const import HyperPrior, ReportedProperty, TieSolver
from .py_bbt import PyBBT
from .utils import multiple_ropes_control_table
from .const import TieSolver, ReportedProperty, HyperPrior

__all__ = [
"HyperPrior",
"PyBBT",
"multiple_ropes_control_table",
"TieSolver",
"ReportedProperty",
"HyperPrior",
"TieSolver",
"multiple_ropes_control_table",
]
10 changes: 8 additions & 2 deletions bbttest/py_bbt.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from collections.abc import Sequence

import numpy as np
import pandas as pd

Expand Down Expand Up @@ -139,7 +141,7 @@ def posterior_table(
rope_value: tuple[float, float] = (0.45, 0.55),
control_model: str | None = None,
selected_models: list[str] | None = None,
columns: list[ReportedProperty] = DEFAULT_PROPERTIES,
columns: Sequence[ReportedProperty | str] = DEFAULT_PROPERTIES,
hdi_proba: float = 0.89,
round_ndigits: int | None = 2,
) -> pd.DataFrame:
Expand Down Expand Up @@ -196,7 +198,11 @@ def posterior_table(
out_table["strong_interpretation_raw"] = np.where(
out_table["mean"] > self._STRONG_INTERPRETATION_BETTER_THRESHOLD,
out_table["left_model"] + ">",
np.where(out_table["mean"] <= self._STRONG_INTERPRETATION_EQUAL_THRESHOLD, "=", "?"),
np.where(
out_table["mean"] <= self._STRONG_INTERPRETATION_EQUAL_THRESHOLD,
"=",
"?",
),
)
out_table["strong_interpretation"] = np.where(
out_table["strong_interpretation_raw"].str.endswith(">"),
Expand Down
28 changes: 20 additions & 8 deletions bbttest/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from typing import Literal

import pandas as pd

from .py_bbt import PyBBT
from typing import Literal


def multiple_ropes_control_table(
model: PyBBT,
Expand Down Expand Up @@ -66,12 +68,22 @@ def multiple_ropes_control_table(
else:
unknown_models.append(row["left_model"])

rows.append({
"rope": rope,
"better_models": better_models if return_as_array else join_char.join(better_models),
"equivalent_models": equivalent_models if return_as_array else join_char.join(equivalent_models),
"worse_models": worse_models if return_as_array else join_char.join(worse_models),
"unknown_models": unknown_models if return_as_array else join_char.join(unknown_models),
})
rows.append(
{
"rope": rope,
"better_models": better_models
if return_as_array
else join_char.join(better_models),
"equivalent_models": equivalent_models
if return_as_array
else join_char.join(equivalent_models),
"worse_models": worse_models
if return_as_array
else join_char.join(worse_models),
"unknown_models": unknown_models
if return_as_array
else join_char.join(unknown_models),
}
)

return pd.DataFrame(rows)
27 changes: 21 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,28 @@ dependencies = [

[dependency-groups]
dev = [
"coverage>=7.12.0",
"jupyter>=1.1.1",
"mypy>=1.18.2",
"pre-commit>=4.5.0",
"ruff>=0.14.6",
"seaborn>=0.13.2",
"coverage",
"jupyter",
"mypy",
"pre-commit",
"ruff",
"seaborn",
]
test = [
"pre-commit",
"pytest",
"ruff",
"mypy",
]

[tool.mypy]
python_version = "3.11"
check_untyped_defs = true # check all functions, this fixes some tests
allow_redefinition = true # we redefine variables a lot for efficiency
# most libraries used are not properly typed in Python, particularly RDKit
ignore_missing_imports = true
disable_error_code = ["import-untyped"]
no_site_packages = true

[tool.uv.build-backend]
module-name = "bbttest"
Expand Down
5 changes: 1 addition & 4 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
include = [
"pyproject.toml",
"benchmarking/**/*.ipynb",
"examples/**/*.py",
"skfp/**/*.py",
"tests/**/*.py",
"bbttest/**"
]
exclude = [
"docs/**"
Expand Down
Empty file added tests/__init__.py
Empty file.
60 changes: 53 additions & 7 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.