neu_eval.overlap¶
The contingency table between two labelings, and the one pass over the voxels.
The only module that reads an array, so the only place a GPU or block boundary shows. A
Contingency keeps its pairs sorted by (a_id, b_id) with no zero counts and no
duplicates, which is what makes c1 + c2 == c3 an exact test of additivity.
Ignored labels are asymmetric by default, because 0 means different things: on side
a, a partly annotated reference, 0 is “not annotated” and leaves the denominator; on
side b, a dense segmentation, 0 inside an annotated region is an error. But many
pipelines label membrane 0. Scored with the default ignore_b=(), that membrane
becomes one huge segment touching every body, a false merge that inflated VOI 2-7x on real
vendor segmentations. Nothing in the array tells the two conventions apart, so pass
ignore_b=(0,) when 0 is membrane, and read frac_scored beside every score.
contingency(a, b).T is not contingency(b, a): the second applies the default
ignore sets to the swapped sides.
Attributes¶
Classes¶
Voxel counts for every |
Functions¶
|
Boolean mask of voxels within |
|
Count the voxels shared by every pair of labels in |
|
Combine tables from regions whose label spaces are independent. |
Module Contents¶
- class neu_eval.overlap.Contingency¶
Voxel counts for every
(a_id, b_id)pair that co-occurs.a_ids,b_idsandcountsare parallel arrays sorted by(a_id, b_id), with only nonzero pairs, always in CPU memory.labelsnames the two sides; it is part of equality and addition, so tables with swapped sides cannot be summed.- a_totals() tuple[numpy.ndarray, numpy.ndarray]¶
(ids, voxels)for sidea, ids ascending. The row marginal.
- b_totals() tuple[numpy.ndarray, numpy.ndarray]¶
(ids, voxels)for sideb, ids ascending. The column marginal.
- keep_pairs(keep: numpy.ndarray) Contingency¶
A table holding only the pairs where
keepis True.Dropped voxels move into
n_ignored, son_scored + n_ignoredstays the size of the region andfrac_scoredstays honest.
- relabel_sides(labels: Sequence[str]) Contingency¶
The same counts, with the two sides named differently.
- restrict(*, a_ids: Iterable | None = None, b_ids: Iterable | None = None) Contingency¶
A table restricted to the given labels on either side, or both.
For example, the labels
neu_eval.assign.completeness()keeps.
- to_frame()¶
A DataFrame of the pairs, columns named after the two sides. Needs pandas (
neu-eval[report]).
- property T: Contingency¶
The same table with the sides exchanged (not the same as re-running
contingency()with the arguments swapped; see the module docstring).
- a_ids: numpy.ndarray¶
- b_ids: numpy.ndarray¶
- counts: numpy.ndarray¶
- ignore_a: frozenset¶
- ignore_b: frozenset¶
- labels: tuple[str, str] = ('a', 'b')¶
- property n_a: int¶
Distinct labels on side
athat survived the ignore sets.
- property n_b: int¶
- n_ignored: int = 0¶
- property n_pairs: int¶
How many
(a_id, b_id)pairs co-occur.
- property n_scored: int¶
Voxels this table counts. Excludes everything
ignore_*or a mask dropped.
- neu_eval.overlap.boundary_band(labels, width: int = 2, *, ignore: Iterable[int] = (0,))¶
Boolean mask of voxels within
widthvoxels of a boundary inlabels.For a boundary-tolerant score, pass
mask=~boundary_band(gt)tocontingency(), so small differences in where a boundary is drawn are not counted. Report it beside the ordinary score, not instead of it: a wide band also removes thin processes entirely. A boundary is any 6-neighbour pair of different labels, ignored values included.
- neu_eval.overlap.contingency(a: Any, b: Any, *, ignore_a: Iterable[int] = (0,), ignore_b: Iterable[int] = (), mask: Any = None, labels: Sequence[str] = ('a', 'b')) Contingency¶
Count the voxels shared by every pair of labels in
aandb.The arrays must have the same shape and already be registered, e.g. read with
read_piece(seg, level=..., crop=gt_piece).ignore_a/ignore_bdrop those label values andmaskrestricts to where it is True; dropped voxels are counted inn_ignored. See the module docstring for the asymmetric defaults, and especially for segmentations that label membrane 0.Runs where the arrays live, CPU or GPU (both must be on the same one); the table comes back in CPU memory.
- neu_eval.overlap.pool(tables: Sequence[Contingency]) Contingency¶
Combine tables from regions whose label spaces are independent.
Use
+for regions of one labeling, where a shared id is one body. Use this for separately annotated crops, where each numbers its bodies from 1 and a shared id means nothing: adding those tables would fuse unrelated cells. Each table’s ids are renumbered and offset past the previous table’s, asneu-vol relabeldoes to a volume.Pooled ids do not name bodies, so the result is for scalar metrics only.
- neu_eval.overlap.DENSE_CELL_LIMIT = 4194304¶