Skip to content
Open
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
32 changes: 26 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,24 @@ The package lives in `bioimage_py/`:
preserved on failure for `resume_from`) and `relabel_consecutive` (derives a consecutive mapping
via a global `unique` reduction, then delegates the block-wise write to `relabel`; in place by
default). `segmentation/multicut.py` ports the
bioimage-cpp-backed multicut cost transform + solvers (`compute_edge_costs`,
`multicut_decomposition` / `_gaec` / `_kernighan_lin`); meant to grow into multicut-based
segmentation. `segmentation/stitching.py` (`stitch_segmentation` / `stitch_tiled_segmentation`)
bioimage-cpp-backed multicut cost transform + whole-graph solvers (`compute_edge_costs`,
`multicut_decomposition` / `multicut_gaec` / `multicut_kernighan_lin`).
`segmentation/lifted_multicut.py` mirrors it for the lifted multicut
(`lifted_multicut_kernighan_lin` / `_gaec` / `_fusion_moves`, `get_lifted_multicut_solver`) plus
lifted-problem construction from a per-node label array (`lifted_edges_from_node_labels`,
`lifted_problem_from_node_labels`). `segmentation/blockwise_multicut.py` and
`segmentation/blockwise_lifted_multicut.py` add the hierarchical domain-decomposition solvers
(`blockwise_multicut` / `blockwise_lifted_multicut`): the per-block sub-problem solve is the **map**
step (distributed via the runner) and the union-find merge + edge contraction + final global solve
are the **in-process reduce**, with the block size doubling each level; both share
`segmentation/_blockwise_common.py` (the numpy reduce primitives, `reduce_problem`, and
`solve_subproblems_distributed`). They take `(graph, costs[, lifted_uv_ids, lifted_costs],
segmentation)` and return a node labeling — the segmentation defines the blocking domain (graph node
`i` == segment `i`); write the labeling to pixels with `relabel`. Unlike the elf reference, the
running node labeling is composed across levels (`node_ids = labels[unique(seg[block])]`) so
`n_levels > 1` is correct, and the graph/costs/labels are persisted to a temp zarr under the runner
temp root (dtypes canonicalized for zarr) for distributed backends. `segmentation/stitching.py`
(`stitch_segmentation` / `stitch_tiled_segmentation`)
merges a tile-wise over-segmentation via a multicut over tile-interface object overlaps — the
per-voxel phases (tile segmentation, overlap counting) run through the runner; RAG build +
multicut solve are in-process private helpers (`_compute_rag` / `_project_node_labels_to_pixels`,
Expand Down Expand Up @@ -148,9 +163,14 @@ the operations above (`stats`, `filters`, `segmentation.label` + `segmentation.w
+ `regionprops`, `copy`, and `downsample` — the latter built on the `ResizedSource` wrapper — the
`evaluation` package: the parallel `contingency_table` primitive plus the metrics built on it —
`segmentation.relabel` (apply a node labeling / relabeling map, in place by default; the canonical
node-label writer, see Conventions) + `segmentation.relabel_consecutive`, and
`segmentation.stitch_segmentation` / `stitch_tiled_segmentation` on the new `segmentation.multicut`
solvers). The slurm-only tests in `tests/test_slurm_runner.py` are skipped unless
node-label writer, see Conventions) + `segmentation.relabel_consecutive`,
`segmentation.stitch_segmentation` / `stitch_tiled_segmentation` on the `segmentation.multicut`
solvers, the whole-graph `segmentation.lifted_multicut` solvers + lifted-problem construction, and the
block-wise hierarchical `segmentation.blockwise_multicut` / `blockwise_lifted_multicut` — per-block
sub-problem solves distributed via the runner (`local` / `subprocess` / `slurm`), the reduce in-process
— verified by `tests/test_blockwise_multicut.py` (block-wise == whole-graph partition on a clean
problem, `local == subprocess` across workers and `n_levels`) and `tests/test_lifted_multicut.py`). The
slurm-only tests in `tests/test_slurm_runner.py` are skipped unless
`sbatch` is on `PATH` and `BIOIMAGE_PY_SHARED_TMP` points at a shared filesystem; `subprocess` stays the
CI proxy for the shared protocol. Note the slurm runner's key subtlety: per-task `.success` sentinels are
written on compute nodes but can take up to the NFS attribute-cache timeout (~60 s) to become visible to
Expand Down
3 changes: 2 additions & 1 deletion bioimage_py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
.. include:: ../docs/installation.md
.. include:: ../docs/usage.md
""" # noqa
from . import evaluation, filters, io, morphology, operations, segmentation, stats # noqa: F401
from . import evaluation, filters, graph, io, morphology, operations, segmentation, stats # noqa: F401
from .copy import copy
from .downsample import downsample
from .runner import SlurmConfig, config_file_path, get_runner, write_slurm_config
Expand All @@ -23,6 +23,7 @@
"segmentation",
"morphology",
"evaluation",
"graph",
"operations",
"io",
"copy",
Expand Down
7 changes: 7 additions & 0 deletions bioimage_py/graph/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Graph operations: distributed region adjacency graphs and edge features."""
from .distributed import distributed_edge_features, distributed_rag

__all__ = [
"distributed_rag",
"distributed_edge_features",
]
Loading
Loading