bioimage_py.evaluation.rand_index

Rand-index derived scores: the adapted rand error and the rand index.

Both are pure reductions of a ContingencyTable; the result is symmetric in the two segmentations, so the table orientation does not matter.

 1"""Rand-index derived scores: the adapted rand error and the rand index.
 2
 3Both are pure reductions of a :class:`ContingencyTable`; the result is symmetric in the two
 4segmentations, so the table orientation does not matter.
 5"""
 6from __future__ import annotations
 7
 8from typing import Optional, Sequence, Tuple
 9
10import numpy as np
11
12from ..runner.config import RunnerConfig
13from ..sources import SourceLike
14from ._common import build_table
15from .contingency_table import ContingencyTable
16
17__all__ = ["rand_scores", "rand_index"]
18
19
20def rand_scores(table: ContingencyTable) -> Tuple[float, float]:
21    """Compute the adapted rand error and the rand index from a contingency table.
22
23    Args:
24        table: A contingency table for the two segmentations.
25
26    Returns:
27        The adapted rand error and the rand index.
28    """
29    n = table.n_points
30    if n == 0:
31        return 0.0, 1.0
32    sum_a2 = float(np.sum(table.sizes_a.astype("float64") ** 2))
33    sum_b2 = float(np.sum(table.sizes_b.astype("float64") ** 2))
34    sum_ab2 = float(np.sum(table.counts.astype("float64") ** 2))
35
36    precision = sum_ab2 / sum_a2
37    recall = sum_ab2 / sum_b2
38    adapted_rand_error = 1.0 - (2 * precision * recall) / (precision + recall)
39    rand_index = 1.0 - (sum_a2 + sum_b2 - 2 * sum_ab2) / (n * n)
40    return float(adapted_rand_error), float(rand_index)
41
42
43def rand_index(
44    segmentation: SourceLike,
45    groundtruth: SourceLike,
46    *,
47    ignore_seg: Optional[Sequence[int]] = None,
48    ignore_gt: Optional[Sequence[int]] = None,
49    num_workers: int = 1,
50    block_shape: Optional[Tuple[int, ...]] = None,
51    job_type: str = "local",
52    job_config: Optional[RunnerConfig] = None,
53    mask: Optional[SourceLike] = None,
54) -> Tuple[float, float]:
55    """Compute the adapted rand error and the rand index between two segmentations.
56
57    Args:
58        segmentation: Candidate segmentation to evaluate (a numpy/zarr/n5 array or a `Source`).
59        groundtruth: The groundtruth segmentation; same shape as ``segmentation``.
60        ignore_seg: Labels to ignore in the segmentation (their voxels are excluded).
61        ignore_gt: Labels to ignore in the groundtruth (their voxels are excluded).
62        num_workers: Number of parallel workers used to build the contingency table.
63        block_shape: Shape of the processing blocks. Defaults to the input chunk shape.
64        job_type: Execution backend: one of ``"local"``, ``"subprocess"`` or ``"slurm"``.
65        job_config: Backend configuration (a `RunnerConfig` / `SlurmConfig`).
66        mask: Optional binary mask; voxels outside the mask are excluded.
67
68    Returns:
69        The adapted rand error and the rand index.
70    """
71    table = build_table(segmentation, groundtruth, ignore_seg=ignore_seg, ignore_gt=ignore_gt,
72                        num_workers=num_workers, block_shape=block_shape, job_type=job_type,
73                        job_config=job_config, mask=mask)
74    return rand_scores(table)
def rand_scores( table: bioimage_py.evaluation.ContingencyTable) -> Tuple[float, float]:
21def rand_scores(table: ContingencyTable) -> Tuple[float, float]:
22    """Compute the adapted rand error and the rand index from a contingency table.
23
24    Args:
25        table: A contingency table for the two segmentations.
26
27    Returns:
28        The adapted rand error and the rand index.
29    """
30    n = table.n_points
31    if n == 0:
32        return 0.0, 1.0
33    sum_a2 = float(np.sum(table.sizes_a.astype("float64") ** 2))
34    sum_b2 = float(np.sum(table.sizes_b.astype("float64") ** 2))
35    sum_ab2 = float(np.sum(table.counts.astype("float64") ** 2))
36
37    precision = sum_ab2 / sum_a2
38    recall = sum_ab2 / sum_b2
39    adapted_rand_error = 1.0 - (2 * precision * recall) / (precision + recall)
40    rand_index = 1.0 - (sum_a2 + sum_b2 - 2 * sum_ab2) / (n * n)
41    return float(adapted_rand_error), float(rand_index)

Compute the adapted rand error and the rand index from a contingency table.

Args: table: A contingency table for the two segmentations.

Returns: The adapted rand error and the rand index.

def rand_index( segmentation: 'SourceLike', groundtruth: 'SourceLike', *, ignore_seg: Optional[Sequence[int]] = None, ignore_gt: Optional[Sequence[int]] = None, num_workers: int = 1, block_shape: Optional[Tuple[int, ...]] = None, job_type: str = 'local', job_config: Optional[bioimage_py.runner.RunnerConfig] = None, mask: 'Optional[SourceLike]' = None) -> Tuple[float, float]:
44def rand_index(
45    segmentation: SourceLike,
46    groundtruth: SourceLike,
47    *,
48    ignore_seg: Optional[Sequence[int]] = None,
49    ignore_gt: Optional[Sequence[int]] = None,
50    num_workers: int = 1,
51    block_shape: Optional[Tuple[int, ...]] = None,
52    job_type: str = "local",
53    job_config: Optional[RunnerConfig] = None,
54    mask: Optional[SourceLike] = None,
55) -> Tuple[float, float]:
56    """Compute the adapted rand error and the rand index between two segmentations.
57
58    Args:
59        segmentation: Candidate segmentation to evaluate (a numpy/zarr/n5 array or a `Source`).
60        groundtruth: The groundtruth segmentation; same shape as ``segmentation``.
61        ignore_seg: Labels to ignore in the segmentation (their voxels are excluded).
62        ignore_gt: Labels to ignore in the groundtruth (their voxels are excluded).
63        num_workers: Number of parallel workers used to build the contingency table.
64        block_shape: Shape of the processing blocks. Defaults to the input chunk shape.
65        job_type: Execution backend: one of ``"local"``, ``"subprocess"`` or ``"slurm"``.
66        job_config: Backend configuration (a `RunnerConfig` / `SlurmConfig`).
67        mask: Optional binary mask; voxels outside the mask are excluded.
68
69    Returns:
70        The adapted rand error and the rand index.
71    """
72    table = build_table(segmentation, groundtruth, ignore_seg=ignore_seg, ignore_gt=ignore_gt,
73                        num_workers=num_workers, block_shape=block_shape, job_type=job_type,
74                        job_config=job_config, mask=mask)
75    return rand_scores(table)

Compute the adapted rand error and the rand index between two segmentations.

Args: segmentation: Candidate segmentation to evaluate (a numpy/zarr/n5 array or a Source). groundtruth: The groundtruth segmentation; same shape as segmentation. ignore_seg: Labels to ignore in the segmentation (their voxels are excluded). ignore_gt: Labels to ignore in the groundtruth (their voxels are excluded). num_workers: Number of parallel workers used to build the contingency table. block_shape: Shape of the processing blocks. Defaults to the input chunk shape. job_type: Execution backend: one of "local", "subprocess" or "slurm". job_config: Backend configuration (a RunnerConfig / SlurmConfig). mask: Optional binary mask; voxels outside the mask are excluded.

Returns: The adapted rand error and the rand index.