Skip to content

Segmentation masks

Segmentation masks as front ends receive them: read, checked, and described before a reconstruction.

A mask is a 3-D array of non-negative integer labels, 0 the medium, axis 0 = z, axis 1 = y, axis 2 = x. The foambryo command and the napari plugin read and check masks with these functions, so both accept and refuse the same arrays with the same messages:

  • read_segmentation_mask(path): a .npy, .npz (array mask, optionally spacing and spacing_unit) or .tif/.tiff file (needs tifffile, foambryo[cli]), checked;
  • check_segmentation_mask(mask): the checks alone, for an array already in memory;
  • segmentation_mask_report(mask): what a reconstruction will meet, counted and changed in nothing: the cells, the cells touching the image box (they will be cut cells), the cells in several pieces, the pieces of medium the tissue encloses, and the very small labels.

Labels need not be consecutive: a label is a name, and the mesh keeps it.

SegmentationMaskError

Bases: ValueError

A mask file that cannot be read, or an array that is not a mask; the message says which and why.

SegmentationMaskReport dataclass

SegmentationMaskReport(shape: tuple[int, ...], n_cells: int, medium_voxels: int, cells_touching_the_image_box: tuple[int, ...], cells_in_several_pieces: dict[int, int] = dict(), enclosed_medium_pieces: int = 0, enclosed_medium_voxels: int = 0, small_label_fraction: float = DEFAULT_SMALL_LABEL_FRACTION, median_cell_voxels: float = 0.0, small_labels: dict[int, int] = dict())

What a reconstruction of a mask will meet, counted; nothing in the mask is changed.

Connectivity is by shared voxel faces (6 neighbours): two pieces of a label that touch only along an edge or at a corner are two pieces, as the mesh will see them.

Attributes:

Name Type Description
shape tuple[int, ...]

the mask's shape.

n_cells int

the number of labels other than 0.

medium_voxels int

the voxels of label 0.

cells_touching_the_image_box tuple[int, ...]

the labels with a voxel on a face of the array; the reconstruction makes them cut cells, whose pressures are not determined.

cells_in_several_pieces dict[int, int]

label -> number of pieces, for the labels in more than one piece.

enclosed_medium_pieces int

the pieces of label 0 that touch no face of the array, so that the tissue encloses them (a hole in the segmentation, read as medium).

enclosed_medium_voxels int

their voxels.

small_label_fraction float

a label below this fraction of the median cell is very small.

median_cell_voxels float

the median number of voxels of a cell (0 without cells).

small_labels dict[int, int]

label -> voxels, for the labels below small_label_fraction of the median cell.

summary

summary() -> str

One line, as foambryo mesh prints it before the reconstruction.

Returns:

Name Type Description
str str

`mask, for information (nothing is changed): cells; touch the image box (cut cells);

str

in several pieces; pieces of medium enclosed by the tissue; smaller than 5% of the median

str

cell ( voxels)`, with this report's fraction in place of 5%.

as_record

as_record() -> dict[str, Any]

The report as plain JSON values, for a run record (the labels of the two maps as strings).

read_segmentation_mask

read_segmentation_mask(path: str | Path) -> tuple[np.ndarray, tuple[float, float, float] | None, str | None]

Read a mask file: the label array, and the spacing and unit an .npz records (else None).

Parameters:

Name Type Description Default
path str | Path

a .npy, .npz or .tif/.tiff file (the suffix in any case). An .npz holds the mask as mask (or as its only array other than spacing and spacing_unit), optionally spacing (three finite numbers > 0, (dz, dy, dx) along axes 0, 1, 2) and spacing_unit (one ASCII word of letters, digits and _ . - / ^). A TIFF's resolution tags are not read, and neither .npy nor TIFF records a spacing.

required

Returns:

Name Type Description
tuple ndarray

the mask (checked by check_segmentation_mask, axis 0 = z), the recorded spacing (dz, dy, dx)

tuple[float, float, float] | None

or None, the recorded unit or None.

Raises:

Type Description
SegmentationMaskError

on an unreadable file, an unsupported suffix, a missing tifffile for a TIFF, or an array that is not a mask. The message names the file.

check_segmentation_mask

check_segmentation_mask(mask: Any, *, name: str = 'the mask') -> np.ndarray

Check that an array is a mask: 3-D, integer labels, none negative.

Parameters:

Name Type Description Default
mask Any

the array (anything np.asarray accepts; a lazy array is read into memory).

required
name str

how the messages name it, for example a file name. Keyword-only.

'the mask'

Returns:

Type Description
ndarray

np.ndarray: np.asarray(mask), unchanged.

Raises:

Type Description
SegmentationMaskError

if it is not 3-D, its values are not integers (floating-point and boolean values are refused), or a label is negative.

segmentation_mask_report

segmentation_mask_report(mask: Any, *, small_label_fraction: float = DEFAULT_SMALL_LABEL_FRACTION) -> SegmentationMaskReport

Describe a mask before it is reconstructed: a report only, nothing is changed.

Parameters:

Name Type Description Default
mask Any

the mask; checked with check_segmentation_mask first.

required
small_label_fraction float

a label with fewer voxels than this fraction of the median cell is reported as very small. Defaults to 0.05 (DEFAULT_SMALL_LABEL_FRACTION). Keyword-only.

DEFAULT_SMALL_LABEL_FRACTION

Returns:

Name Type Description
SegmentationMaskReport SegmentationMaskReport

the counts.

Raises:

Type Description
SegmentationMaskError

if the array is not a mask.