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
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Install package and docs tooling
run: python -m pip install -v ".[test]" pdoc
- name: Build docs
run: pdoc bioimage_cpp -o docs
run: PYTHONPATH=src pdoc bioimage_cpp -o docs
- uses: actions/upload-pages-artifact@v3
with:
path: docs
Expand Down
109 changes: 102 additions & 7 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,113 @@ on:
release:
types: [published]

permissions:
contents: read

jobs:
wheels:
name: ${{ matrix.os }}
build_wheels:
name: wheels-${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-13, macos-14, windows-latest]
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v4
- uses: pypa/cibuildwheel@v2.18

- name: Build wheels
uses: pypa/cibuildwheel@v3.4.1
env:
CIBW_BUILD: "cp310-* cp311-* cp312-*"
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: "python -c \"import bioimage_cpp\" && pytest {project}/tests"
CIBW_BUILD: "cp310-* cp311-* cp312-* cp313-* cp314-*"
CIBW_SKIP: "*-win32 *-manylinux_i686 *-musllinux_*"
CIBW_ARCHS_MACOS: "native"
CIBW_TEST_REQUIRES: "pytest pooch scipy"
CIBW_TEST_COMMAND: "python -c \"import bioimage_cpp; print(bioimage_cpp.__file__)\" && pytest -q {project}/tests"

- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}
path: wheelhouse/*.whl

build_sdist:
name: sdist
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install build tooling
run: python -m pip install build twine

- name: Build sdist
run: python -m build --sdist

- name: Check sdist metadata
run: python -m twine check dist/*

- name: Upload sdist
uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz

publish-testpypi:
name: publish-to-testpypi
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'

environment:
name: testpypi
url: https://test.pypi.org/p/bioimage-cpp

permissions:
id-token: write

steps:
- name: Download distributions
uses: actions/download-artifact@v4
with:
pattern: cibw-*
path: dist
merge-multiple: true

- name: List distributions
run: ls -lh dist

- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/

publish-pypi:
name: publish-to-pypi
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'

environment:
name: pypi
url: https://pypi.org/p/bioimage-cpp

permissions:
id-token: write

steps:
- name: Download distributions
uses: actions/download-artifact@v4
with:
pattern: cibw-*
path: dist
merge-multiple: true

- name: List distributions
run: ls -lh dist

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ venv/
*.npz

CLAUDE.md
pypi-release.txt
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,10 @@ Don't add `std::chrono` snippets ad hoc; use the existing macros so future profi

## Documentation

`README.md` covers: what `bioimage-cpp` is and isn't, install/build, minimal examples, design philosophy. Public functions need concise docstrings documenting input shapes, supported dtypes, output shapes/dtypes, copy behavior, background-label behavior (if relevant), and axis/coordinate conventions.

Update `MIGRATION_GUIDE.md` whenever public functionality changes, so users migrating from `nifty`/`affogato` see the corresponding `bioimage-cpp` API, behavioral differences, and intentional improvements.

The documentation is build via pdoc, see `.github/workflow/docs.yaml`.

## Checklist when modifying code

1. Reuse existing `detail/` helpers; add new shared ones rather than duplicating.
Expand Down
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 bioimage-cpp contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
72 changes: 2 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,5 @@
# bioimage-cpp

Stand-alone implementation of image analysis and segmentaton functionality in C++ with minimal python bindings.
Image processing and segmentation functionality in C++ with light-weight python bindings through nanobind and minimal dependencies to enable distribution via pip.

`bioimage-cpp` is a small C++/Python package for dependency-light bioimage-analysis algorithms that are difficult to install from larger C++ libraries. It exposes NumPy-based Python APIs backed by a focused C++20 core.

## Install

```bash
python -m pip install bioimage-cpp
```

## Build from source

```bash
python -m pip install -v ".[test]"
pytest -q
```

## Example

```python
import numpy as np
import bioimage_cpp as bic

labels = np.array([1, 3, 2, 1], dtype=np.uint64)
relabeling = {1: 10, 2: 20, 3: 30}

out = bic.utils.take_dict(relabeling, labels)
# array([10, 30, 20, 10], dtype=uint64)
```

```python
affinities = np.ones((2, 4, 4), dtype=np.float32)
offsets = [[0, 1], [1, 0]]

segmentation = bic.segmentation.mutex_watershed(
affinities,
offsets,
number_of_attractive_channels=2,
)
```

```python
image = np.arange(64, dtype=np.float32).reshape(8, 8)
matrix = np.array([[1.0, 0.0, 0.5], [0.0, 1.0, -1.0]])

transformed = bic.transformation.affine_transform(
image,
matrix,
order=3,
fill_value=0,
)
```

```python
graph = bic.graph.UndirectedGraph.from_edges(4, [[0, 1], [1, 2], [2, 3]])
graph.find_edge(2, 1)
# 1

grid = bic.graph.grid_graph((64, 64))
grid.number_of_edges
# 8064

edge_weights = bic.graph.grid_boundary_features(grid, boundary_map)
local_weights, valid_edges, lifted_uvs, lifted_weights, offset_ids = (
bic.graph.grid_affinity_features_with_lifted(grid, affinities, offsets)
)
```

## Scope

The project is not a compatibility layer for `nifty`, `vigra`, or other large libraries. It keeps I/O and heavy dependencies out of the C++ core; callers should use existing Python packages for file formats and pass NumPy arrays into `bioimage-cpp`.
Please refer to [the documentation](https://computational-cell-analytics.github.io/bioimage-cpp/) for details.
21 changes: 21 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,24 @@ authors = [
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Programming Language :: C++",
"Programming Language :: C++ :: 20",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Scientific/Engineering :: Image Processing",
]

[project.urls]
Homepage = "https://github.com/computational-cell-analytics/bioimage-cpp"
Repository = "https://github.com/computational-cell-analytics/bioimage-cpp"
Issues = "https://github.com/computational-cell-analytics/bioimage-cpp/issues"

[project.optional-dependencies]
test = ["pytest", "pooch", "scipy"]
data = ["pooch"]
Expand All @@ -31,6 +42,16 @@ data = ["pooch"]
cmake.version = ">=3.21"
cmake.build-type = "Release"
wheel.packages = ["src/bioimage_cpp"]
sdist.exclude = [
"pypi-release.txt",
"dist/",
"wheelhouse/",
"_skbuild/",
"build/",
"*.egg-info/",
".pytest_cache/",
"__pycache__/",
]

[tool.pytest.ini_options]
testpaths = ["tests"]
43 changes: 40 additions & 3 deletions src/bioimage_cpp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""`bioimage_cpp` implements functionality needed for image procesing in C++.
"""`bioimage_cpp` implements image processing and segmentation functionality in C++.
It generates light-weight python bindings with nanobind with minimal dependencies to enable distribution via pip.

The main goal of this library is to provide functionality that is missing from scipy or scikit-image or
to provide more performant versions of functionality from these libraries.
The main goal of this library is to provide functionality that is missing from scipy or scikit-image,
or to provide more performant versions of functionality from these libraries.

The functionality implemented here bundles and improves algorithms etc. from:
- [affogato](https://github.com/constantinpape/affogato)
Expand All @@ -19,6 +19,43 @@

TODO: document once on pip / conda

## Functionality

This library provides the following functionality:
- `affinities`: functionality for deriving affinities from segmentations.
- `filters`: efficient implementation of convolutional image filters.
- `graph`: graph creation and graph (partitioning) algorithms.
- `segmentation`: image segmentation functionality.
- `transformation`: affine transformations.
- `util`: misc utility functionality.

## Example

Below is a simple example for creating and partitioning a graph with this library.
For more realistic use-cases check out [the migration guide](migration-guide).

```python
import numpy as np
import bioimage_cpp as bic

# Create a graph with 50 nodes.
graph = bic.graph.undirected_graph(number_of_nodes=50)

# Insert a bunch of edges forming a chain.
graph.insert_edges(
np.concatenate([np.arange(0, 49)[:, None], np.arange(1, 50)[:, None]], axis=1)
)

# Create edge weights in [-1, 1].
weights = 2 * np.random.rand(graph.number_of_edges) - 1

# Partition the graph via multicut (greedy solver).
objective = bic.graph.MulticutObjective(graph, weights)
solver = bic.graph.GreedyAdditiveMulticut()
partition = solver.optimize(objective)
print("Partitioned into", len(np.unique(partition)), "elements")
```

.. include:: ../../MIGRATION_GUIDE.md
"""

Expand Down
Loading