/** * Multi-label segmentation helpers (pure — no VTK, no DOM, unit-testable). * * A single labelsTr/.nii.gz can encode many organs as integer voxel values * (e.g. TotalSegmentator: 1..117). These split such a volume's scalar array into the * distinct label values present, and into a per-value binary (0/1) mask the renderer * can extract as one coloured iso-surface. The VTK wrappers live in `niftiLoader`. */ /** Distinct non-zero integer label values present in a segmentation's scalar array, ascending. */ export function distinctLabelValues(scalars: ArrayLike): number[] { const seen = new Set(); for (let i = 0; i < scalars.length; i++) { const v = scalars[i]; if (v > 0 && Number.isInteger(v)) seen.add(v); } return [...seen].sort((a, b) => a - b); } /** A binary (0/1) Uint8Array mask: 1 where the scalar equals `value`, else 0. */ export function binaryLabelMask(scalars: ArrayLike, value: number): Uint8Array { const out = new Uint8Array(scalars.length); for (let i = 0; i < scalars.length; i++) { if (scalars[i] === value) out[i] = 1; } return out; } /** True when a segmentation holds more than one distinct organ label (so it is worth splitting). */ export function isMultiLabel(scalars: ArrayLike): boolean { return distinctLabelValues(scalars).length > 1; }