topo.postprocess

Instance segmentation postprocessing: flow tracking + convergence clustering.

Converts predicted flow fields into instance labels via: 1. Euler integration — track each foreground voxel along the flow field 2. Convergence clustering — group voxels by where they end up (grid hash + union-find) 3. Optional cleanup — split disconnected components, orphan recovery, flow QC

Three morphology groups with different strategies: - Group 1 (convex): standard tracking + clustering - Group 2 (elongated): tracking + clustering + split disconnected components - Group 3 (thin): tracking + clustering + split + orphan recovery

Attributes

logger

Functions

run_instance_segmentation(→ Dict[str, numpy.ndarray])

Convert semantic predictions + flow fields into instance labels.

postprocess_single(→ numpy.ndarray)

Postprocess a single class: track flows → cluster → cleanup.

track_flows(→ tuple[numpy.ndarray, numpy.ndarray])

Euler integration: move each foreground voxel along the flow field.

cluster_convergence(→ numpy.ndarray)

Cluster particles by final positions using grid hashing + union-find.

split_disconnected(→ numpy.ndarray)

Split disconnected components, absorbing small fragments into nearest.

remove_bad_flow_masks(→ numpy.ndarray)

Discard masks whose recomputed flows disagree with predicted flows.

compact_relabel(→ numpy.ndarray)

Relabel instance IDs to be contiguous starting from 1.

filter_small(→ numpy.ndarray)

Remove instances smaller than min_size and compact relabel.

Module Contents

topo.postprocess.logger
topo.postprocess.run_instance_segmentation(semantic_pred: numpy.ndarray, flow_pred: numpy.ndarray, class_names: list[str] | None = None, class_config: Dict[str, dict] | None = None, flow_error_threshold: float = 0.0) Dict[str, numpy.ndarray]

Convert semantic predictions + flow fields into instance labels.

Parameters:
  • semantic_pred – [N_classes, D, H, W] per-class probabilities.

  • flow_pred – [N*3, D, H, W] per-class flow predictions.

  • class_names – List of N class names. Defaults to EVALUATED_INSTANCE_CLASSES.

  • class_config – Per-class postprocessing config. Defaults to resolution-based config.

  • flow_error_threshold – If > 0, discard masks whose recomputed flows differ from predicted flows by more than this MSE threshold.

Returns:

Dict mapping class name -> [D, H, W] int32 instance labels.

topo.postprocess.postprocess_single(sem_mask: numpy.ndarray, flow: numpy.ndarray, n_steps: int = 100, step_size: float = 1.0, convergence_radius: float = 4.0, min_size: int = 50, group: int = 1) numpy.ndarray

Postprocess a single class: track flows → cluster → cleanup.

Parameters:
  • sem_mask – [D, H, W] bool — foreground mask.

  • flow – [3, D, H, W] float — flow field (dz, dy, dx).

  • n_steps – Euler integration steps.

  • step_size – Step size per iteration.

  • convergence_radius – Merge clusters within this radius.

  • min_size – Remove instances smaller than this.

  • group – Morphology group (1=convex, 2=elongated, 3=thin).

Returns:

[D, H, W] int32 — instance labels.

Return type:

instances

topo.postprocess.track_flows(sem_mask: numpy.ndarray, flow: numpy.ndarray, n_steps: int, step_size: float = 1.0) tuple[numpy.ndarray, numpy.ndarray]

Euler integration: move each foreground voxel along the flow field.

Parameters:
  • sem_mask – [D, H, W] bool — foreground mask.

  • flow – [3, D, H, W] float — predicted flow (dz, dy, dx).

  • n_steps – Number of integration steps.

  • step_size – Distance per step.

Returns:

[N, 3] int — original voxel positions. final_positions: [N, 3] float64 — where particles ended up.

Return type:

fg_coords

topo.postprocess.cluster_convergence(fg_coords: numpy.ndarray, final_positions: numpy.ndarray, volume_shape: tuple, convergence_radius: float, min_size: int) numpy.ndarray

Cluster particles by final positions using grid hashing + union-find.

Parameters:
  • fg_coords – [N, 3] int — original voxel coords.

  • final_positions – [N, 3] float — converged positions.

  • volume_shape – (D, H, W).

  • convergence_radius – Merge clusters within this radius.

  • min_size – Remove clusters smaller than this.

Returns:

[D, H, W] int32 — instance labels.

Return type:

instances

topo.postprocess.split_disconnected(instances: numpy.ndarray, min_fragment_ratio: float = 0.1) numpy.ndarray

Split disconnected components, absorbing small fragments into nearest.

When an elongated instance (e.g. mito) gets clustered correctly but has a thin bridge that breaks connectivity, naive splitting creates spurious fragments. Instead, we only keep components above min_fragment_ratio of the parent instance size. Smaller fragments are reassigned to the nearest large component via distance transform.

Parameters:
  • instances – [D, H, W] int32 — instance labels.

  • min_fragment_ratio – Components smaller than this fraction of the parent instance are absorbed rather than split off.

Returns:

Relabeled instance volume.

topo.postprocess.remove_bad_flow_masks(instances: numpy.ndarray, pred_flow: numpy.ndarray, threshold: float = 0.4) numpy.ndarray

Discard masks whose recomputed flows disagree with predicted flows.

For each instance, compute unit vectors from voxels to center of mass, then compare to the network’s predicted flows. Masks with MSE > threshold are removed.

Parameters:
  • instances – [D, H, W] int32 — instance labels.

  • pred_flow – [3, D, H, W] float — predicted flow field.

  • threshold – MSE threshold above which masks are discarded.

Returns:

[D, H, W] int32 — filtered instance labels.

Return type:

instances

topo.postprocess.compact_relabel(instances: numpy.ndarray) numpy.ndarray

Relabel instance IDs to be contiguous starting from 1.

topo.postprocess.filter_small(instances: numpy.ndarray, min_size: int) numpy.ndarray

Remove instances smaller than min_size and compact relabel.