brain-zero / tests /test_build_parcellation.py
rfick's picture
Squash history: one commit holding the current files
6bc44d6
Raw History Blame Contribute Delete
3.56 kB
"""The parcellation's pure-numpy pieces: the node table (84 nodes, 14 lobar groups), the majority vote and the
derived labels / stop mask. No SynthSeg, no TensorFlow, no download -- everything here is synthetic and fast."""
import numpy as np
import pytest
from tools import build_parcellation as BP
def test_node_table_has_84_nodes_and_14_lobar_groups():
nodes = BP.node_table()
assert len(nodes) == 84
assert len(set(n["id"] for n in nodes)) == 84
assert set(n["id"] for n in nodes) == set(range(1, 85))
left = [n for n in nodes if n["hemisphere"] == "left"]
right = [n for n in nodes if n["hemisphere"] == "right"]
assert len(left) == 42 and len(right) == 42
cortical = [n for n in nodes if n["lobe"] != "subcortical"]
subcortical = [n for n in nodes if n["lobe"] == "subcortical"]
assert len(cortical) == 68 and len(subcortical) == 16
regions = BP.regions_payload()
groups = regions["lobes"]
assert len(groups) == 14 and len(set(groups)) == 14
for lobe in BP.LOBES:
assert f"{lobe}-left" in groups and f"{lobe}-right" in groups
def test_node_table_ids_are_unique_per_fs_label_and_hemisphere():
nodes = BP.node_table()
keys = [(n["fs_label"], n["hemisphere"]) for n in nodes]
assert len(set(keys)) == len(keys)
def test_supersampled_affine_centres_subvoxels_within_the_parent_voxel():
ref_affine = np.array([[2.5, 0, 0, 10.0], [0, 2.5, 0, -5.0], [0, 0, 2.5, 3.0], [0, 0, 0, 1]])
for factor in (1, 2, 4, 5):
sup = BP._supersampled_affine(ref_affine, factor)
# the mean of the factor**3 sub-voxel centres of parent voxel (2, 1, 0) must equal that parent's own centre
idx = np.arange(factor)
grid = np.stack(np.meshgrid(idx, idx, idx, indexing="ij"), axis=-1).reshape(-1, 3)
sub_index = np.array([2, 1, 0]) * factor + grid
world = sub_index @ sup[:3, :3].T + sup[:3, 3]
parent_world = ref_affine[:3, :3] @ [2, 1, 0] + ref_affine[:3, 3]
np.testing.assert_allclose(world.mean(axis=0), parent_world, atol=1e-9)
def test_majority_vote_picks_the_plurality_label_under_identity_registration():
# a tiny "T1" label volume at 1 mm, two blocks of 3x3x3 mostly-9 voxels with a 2-voxel minority, at the origin;
# the "diffusion" grid is 3x coarser (3 mm) and exactly covers one combined super-voxel.
seg = np.full((3, 3, 3), 9, dtype=np.int32)
seg[0, 0, 0] = 5
seg[0, 0, 1] = 5
seg_affine = np.eye(4)
ref_affine = np.diag([3.0, 3.0, 3.0, 1.0])
ref_affine[:3, 3] = 1.0 # the single ref voxel's centre sits at the seg block's centre
majority = BP.majority_vote(seg, seg_affine, (1, 1, 1), ref_affine, np.eye(4), factor=3)
assert majority.shape == (1, 1, 1)
assert majority[0, 0, 0] == 9 # 25 votes for 9 against 2 for 5
def test_labels_and_stop_mask_from_majority_labels():
majority = np.array([[[0, 2, 1001]]]) # background, left cerebral WM, left bankssts
labels, stop = BP.labels_and_stop_mask(majority)
assert labels[0, 0, 0] == 0
assert labels[0, 0, 2] == 1 # bankssts is fs id 1001, the first (lowest) left-hemisphere node
assert stop.tolist() == [[[False, True, False]]]
def test_label_volumes_mm3():
labels = np.array([0, 0, 1, 1, 1, 2], dtype=np.int16)
vols = BP.label_volumes_mm3(labels, voxel_volume_mm3=8.0)
assert vols == {1: 24.0, 2: 8.0}
def test_every_cortical_name_has_a_lobe():
assert set(BP.LOBE_OF_CORTICAL) == set(BP.CORTICAL_NAMES.values())
assert set(BP.LOBE_OF_CORTICAL.values()) <= set(BP.LOBES)