neu_eval.compare¶
One call from two registered pieces to everything a comparison produces.
compare(a, b) builds the table once, computes every metric from it, ranks and locates
the disagreements, and, given a reviewed verdict file, adds an adjudicated score. A
Report holds it all, raw and adjudicated side by side.
The two pieces must describe the same physical box. Read the second with
read_piece(seg, level=..., crop=gt_piece), which converts the box using that level’s
own voxel size and origin; matching shapes by hand or assuming a 2 ** level factor can
shift it by part of a voxel. compare() checks the frames agree.
Attributes¶
Classes¶
Everything one comparison produced. |
Functions¶
|
Compare two registered pieces and return everything the comparison produced. |
|
Reference labels whose bounding box is far larger than the label itself. |
|
Every scalar metric for one table, as a single flat row. |
Module Contents¶
- class neu_eval.compare.Report¶
Everything one comparison produced.
summaryandadjudicated_summaryare flat dicts, so many comparisons make a DataFrame directly. Theadjudicated_*fields areNonewhen no verdicts were given; verdicts that changed nothing give a summary equal to the raw one, andverdict_tallyshows why.- headline() str¶
A one-line summary for a terminal or a log.
- adjudicated: neu_eval.overlap.Contingency | None = None¶
- adjudicated_summary: dict | None = None¶
- contingency: neu_eval.overlap.Contingency¶
- property kind_counts: dict[str, int]¶
- labels: tuple[str, str]¶
- rows: list[dict]¶
- summary: dict¶
- verdict_tally: dict | None = None¶
- warnings: list[str] = []¶
- neu_eval.compare.compare(a: Any, b: Any, *, labels: Sequence[str] = ('gt', 'seg'), ignore_a: Sequence[int] = (0,), ignore_b: Sequence[int] = (), mask: Any = None, top: int | None = 200, min_frac: float = 0.05, min_voxels: int = 1, rank: str = 'severity', locate: bool = True, point_at: str = 'seam', verdicts: Mapping[str, str] | None = None, check_frames: bool = True, check_scattered: bool = True) Report¶
Compare two registered pieces and return everything the comparison produced.
ais the reference andbthe side assessed; that sets only the defaultignore_a=(0,), the output names, and the direction ofvoi_split/voi_merge.locate=Falseskips the per-pair distance transforms, the one cost that scales withtop; useful when only the numbers are wanted.point_atis passed toneu_eval.disagree.locate().verdicts(pair_key-> verdict, from a reviewed disagreement file) adds an adjudicated score alongside the raw one.
- neu_eval.compare.scattered_labels(piece: Any, c: neu_eval.overlap.Contingency, *, factor: float = SCATTER_FACTOR, min_voxels: int = SCATTER_MIN_VOXELS) list[dict]¶
Reference labels whose bounding box is far larger than the label itself.
This mainly catches a reference assembled from several annotated crops that each number their bodies from 1: without
neu-vol relabel, one id names a different cell in each crop, a low-numbered “body” is a chimera of unrelated cells, and every metric is meaningless with no error.It warns rather than raises, because a genuinely fragmented annotation looks the same from the voxels; the warning carries the numbers so the reader can judge.
- neu_eval.compare.summarize(c: neu_eval.overlap.Contingency, *, at: tuple[float, ...] = (0.5, 0.9)) dict¶
Every scalar metric for one table, as a single flat row.
- neu_eval.compare.SCATTER_FACTOR = 1000.0¶
- neu_eval.compare.SCATTER_MIN_VOXELS = 100¶