itasc.segmentation

Segmentation package — shared utilities and submodule re-exports.

exception itasc.segmentation.CancelledError[source]

Bases: Exception

Raised when a cooperative cancel signal is observed mid-computation.

class itasc.segmentation.CellDivergenceParams(fg_window=51, fg_strength=0.0, fg_threshold=0.1, contour_window=51, contour_strength=1.0, contour_threshold=0.0, contour_norm_pct=99.0, memory_tau=0.0, memory_floor=0.01, balance=0.98, feature_strength=100.0, n_workers=4)[source]

Bases: object

Parameters for the unary-only divergence cell pipeline.

Defaults match the values that held across pos00/pos01 in the prototype.

Parameters:
fg_window: int = 51

Local-mean window for the foreground residual (px, forced odd).

fg_strength: float = 0.0

0 = raw sigmoid, 1 = full subtraction.

Type:

Foreground residual strength

fg_threshold: float = 0.1

Cleaned-foreground cutoff producing the fill mask (sigmoid scale).

contour_window: int = 51

Local-mean window for the contour residual (px, forced odd).

contour_strength: float = 1.0

0 = raw, 1 = full local-mean subtraction.

Type:

Contour residual strength

contour_threshold: float = 0.0

Noise floor on the normalized contour [0, 1]; below → 0.

contour_norm_pct: float = 99.0

Percentile of the positive contour signal mapped to 1.0 in [0, 1].

memory_tau: float = 0.0

EMA crossover (~the contour value you call “weak”). 0 = off.

memory_floor: float = 0.01

Minimum per-frame alpha; ghost half-life (~69 frames @ 0.01).

balance: float = 0.98

Contour↔foreground split r in [0, 1] (1 = pure contour). See balance_strength_to_weights().

feature_strength: float = 100.0

Overall feature weight s >= 0 relative to the base cost of 1.

n_workers: int = 4

Parallel workers for geodesic computation (compute only).

class itasc.segmentation.CellDivergenceResult(foreground_raw, foreground_clean, contours_raw, contours_clean, foreground_mask, cost_field, labels)[source]

Bases: object

All pipeline intermediates plus the final labels.

Arrays are (T, Y, X) for a full-stack run and (Y, X) for a single-frame (frame given) run.

Parameters:
foreground_raw: ndarray

Raw input foreground map (sigmoid).

foreground_clean: ndarray

Foreground after residual cleanup (sigmoid scale).

contours_raw: ndarray

Raw input contour map (positive divergence).

contours_clean: ndarray

Contours after residual + normalize + floor (and temporal smoothing for a full-stack run).

foreground_mask: ndarray

(foreground_clean > fg_threshold) | (nucleus > 0).

Type:

Fill territory

cost_field: ndarray

Weighted geodesic cost over the mask; inf outside.

labels: ndarray | None

Cell labels — the unary argmin (tracked nucleus IDs). None when the geodesic label assignment was skipped (with_labels=False).

class itasc.segmentation.CellForegroundResult(foreground_raw, foreground_clean, foreground_mask)[source]

Bases: object

Foreground-path intermediates — pipeline stages 1 + 3, foreground only.

Arrays are (T, Y, X) for a full-stack run and (Y, X) for a single-frame (frame given) run.

Parameters:
foreground_raw: ndarray

Raw input foreground map (sigmoid), clipped to [0, 1].

foreground_clean: ndarray

Foreground after residual cleanup (sigmoid scale).

foreground_mask: ndarray

(foreground_clean > fg_threshold) unioned with the nucleus seeds when nuc is supplied.

Type:

Fill territory

class itasc.segmentation.CellICMState(fg_mask, nuc_tracks, label_ids, unary_dense=None)[source]

Bases: object

Cached energy-landscape data for the unary segmentation.

Created by initialize_icm(). All arrays are stored as their solver-ready dtypes (float32 / uint32 / bool).

Parameters:
fg_mask: ndarray

(T, Y, X) bool — foreground mask (includes nucleus pixels).

nuc_tracks: ndarray

(T, Y, X) uint32 — nucleus track IDs (0 = no nucleus).

label_ids: ndarray

(K,) uint32 — sorted global set of label (track) IDs.

unary_dense: ndarray | None = None

Deprecated. Previously held the dense (T, Y, X, K) unary cost volume; initial labels are now computed with a streaming argmin (_argmin_init_from_dict()) so this is left None to avoid the multi-gigabyte allocation.

property shape: tuple[int, int, int]
property n_labels: int
class itasc.segmentation.CellLabelICMParams(balance=1.0, feature_strength=4.0, n_workers=1)[source]

Bases: object

Parameters for the unary-only geodesic cell segmentation.

Parameters:
balance: float = 1.0

1 = pure contour, 0 = pure foreground. See balance_strength_to_weights().

Type:

Contour↔foreground split r in [0, 1]

feature_strength: float = 4.0

Overall feature weight s >= 0 relative to the fixed base cost of 1: how strongly contour/foreground bend the walk away from a plain geodesic distance Voronoi. 0 = pure distance Voronoi.

n_workers: int = 1

Parallel worker processes for geodesic unary computation. 1 = sequential. Values > 1 use fork-based multiprocessing to compute frames in parallel.

class itasc.segmentation.ContourFilterParams(median_kernel_time=1, median_kernel_space=1, gaussian_sigma_time=0.0, gaussian_sigma_space=0.0, memory_tau=0.0, memory_floor=0.01)[source]

Bases: object

Parameters for spatial and temporal contour-map filtering.

Parameters:
  • median_kernel_time (int)

  • median_kernel_space (int)

  • gaussian_sigma_time (float)

  • gaussian_sigma_space (float)

  • memory_tau (float)

  • memory_floor (float)

median_kernel_time: int
median_kernel_space: int
gaussian_sigma_time: float
gaussian_sigma_space: float
memory_tau: float
memory_floor: float
class itasc.segmentation.LineageModel(n_frames, lanes)[source]

Bases: object

All track lanes plus the total frame count, for the lineage panel.

Parameters:
n_frames: int
lanes: tuple[TrackLane, ...]
lane_for(cell_id)[source]
Return type:

TrackLane | None

Parameters:

cell_id (int)

class itasc.segmentation.TrackLane(cell_id, segments)[source]

Bases: object

One track id and the frame segments where it is present.

Parameters:
cell_id: int
segments: tuple[TrackSegment, ...]
property first_frame: int
property last_frame: int
property n_frames: int
property has_gap: bool
class itasc.segmentation.TrackSegment(start, end)[source]

Bases: object

A contiguous run of frames [start, end] (inclusive) for one track.

Parameters:
start: int
end: int
property length: int
itasc.segmentation.assemble_cost_field(contours_t, fg_t, alpha_unary, fg_scores_t=None, gamma_unary=0.0)[source]

Per-pixel geodesic cost over a single frame’s foreground mask.

cost = 1 + alpha_unary * contour + gamma_unary * (1 - fg_score) inside the mask, inf elsewhere. This is the exact field the geodesic walk traverses; sharing it between _compute_frame_geodesic() and the cell widget’s live preview guarantees the preview shows the same array the solver uses rather than a re-derivation.

Return type:

ndarray

Parameters:
itasc.segmentation.balance_strength_to_weights(balance, feature_strength)[source]

Map the (balance, feature_strength) knobs to raw cost-field weights.

The geodesic cost field is 1 + alpha * contour + gamma * (1 - fg_score). Because the final labels come from a per-pixel argmin over geodesic distances, multiplying the whole field by any positive constant leaves the result unchanged — overall scale is a free gauge. That leaves exactly two observable degrees of freedom, exposed here as:

  • balance (r in [0, 1]) — the contour↔foreground split (1 = pure contour, 0 = pure foreground).

  • feature_strength (s >= 0) — how strongly either feature bends the walk away from a plain distance Voronoi, relative to the fixed base of 1 (0 = pure distance Voronoi).

with alpha = s * r and gamma = s * (1 - r).

Return type:

tuple[float, float]

Parameters:
itasc.segmentation.build_lineage(tracked)[source]

Build a LineageModel from a (T, Y, X) tracked label stack.

A singleton Z axis ((T, 1, Y, X)) is squeezed; a single 2D frame is treated as one timepoint. Lanes are sorted by track id so a cell keeps its row across refreshes; correction actions (retrack, extend, relabel, …) that change a track’s id move it to its new sorted position on the next refresh.

Return type:

LineageModel

Parameters:

tracked (ndarray)

itasc.segmentation.clean_and_smooth_contours(contours, params)[source]

Full-stack contour cleanup + temporal smoothing — pipeline stages 1+2.

Returns the (T, Y, X) cleaned (residual → global-percentile normalize → floor) and, when memory_tau > 0 and there is more than one frame, temporally smoothed contour stack — exactly the contours_clean the full run feeds the segmenter.

The widget’s live preview computes this once over the whole movie, caches it, and slices the current frame back into segment_cells_divergence() via contours_clean_override so the previewed cost field / labels for a frame match the full run (which the per-frame path cannot, since both the global percentile and the bidirectional EMA need every frame).

Return type:

ndarray

Parameters:
itasc.segmentation.commit_labels(labels, output_path)[source]

Write label array to TIFF.

Labels are stored as uint16 when they fit (compact, backward compatible) and promoted to uint32 otherwise. Casting a track id above 65535 down to uint16 would silently wrap and merge distinct cells, so the dtype is chosen from the actual maximum label.

Return type:

None

Parameters:
itasc.segmentation.compute_cell_foreground(foreground, params, nuc=None, *, frame=None)[source]

Foreground cleanup + fill mask, independent of contours and the geodesic.

Drives the cell widget’s dedicated foreground-tuning stage. It runs exactly the foreground half of segment_cells_divergence() — the local-mean residual cleanup (stage 1) and the fill-mask threshold (stage 3) — with no contour cleanup, cost field, or geodesic walk, so foreground tuning stays cheap and does not require the contour map.

nuc is optional: when given, its seeds are unioned into the mask exactly as the full run does ((foreground_clean > fg_threshold) | (nuc > 0)), so the previewed mask matches the territory segmentation will fill; when None the mask is the bare threshold, letting the foreground be tuned before nucleus tracking exists.

frame selects a single frame (2-D result); None processes the whole stack (3-D result).

Return type:

CellForegroundResult

Parameters:
itasc.segmentation.compute_filtered_contour_maps(contours, params)[source]

Return contour maps after median, Gaussian, and memory filtering.

Return type:

ndarray

Parameters:
itasc.segmentation.initialize_icm(nuc_tracks, fg_mask, contours, params, *, foreground_scores=None, cache_dir=None, progress_cb=None)[source]

Compute geodesic unaries and build labels (per-pixel argmin).

Parameters:
Return type:

tuple[CellICMState, ndarray]

Returns:

  • state (CellICMState)

  • init_labels ((T, Y, X) uint32)

itasc.segmentation.segment_cells_divergence(contours, foreground, nuc, params, *, frame=None, with_labels=True, contours_clean_override=None, foreground_mask_override=None, progress_cb=None)[source]

Run the unary-only divergence pipeline and return all intermediates.

Parameters:
  • contours (ndarray) – Cached divergence maps (raw positive divergence and the sigmoid foreground, respectively).

  • foreground (ndarray) – Cached divergence maps (raw positive divergence and the sigmoid foreground, respectively).

  • nuc (ndarray) – Tracked nucleus seeds.

  • params (CellDivergenceParams)

  • frame (int | None) – When given, only that frame is processed and temporal smoothing is skipped (it needs the whole stack); the result arrays are 2-D. When None, the whole stack is processed including temporal smoothing.

  • with_labels (bool) – When False, the geodesic Voronoi label assignment (the single slowest step) is skipped: every cleanup intermediate plus the weighted cost field is still returned, but result.labels is None. The live preview uses this to stay responsive — the cost field already explains every boundary the labels would land on.

  • contours_clean_override (ndarray | None) – Single-frame-only. When given (with frame set), this pre-cleaned — and, when temporal smoothing is on, pre-smoothed — contour frame is used as contours_clean instead of re-running the per-frame cleanup. The widget passes a frame sliced from clean_and_smooth_contours() so the single-frame cost field / labels match the full run exactly (the per-frame path cannot, as it lacks the whole-movie percentile and EMA). Ignored when frame is None.

  • foreground_mask_override (ndarray | None) – Precomputed fill mask to segment inside, replacing the internally derived (foreground_clean > fg_threshold) | (nuc > 0). The cell widget’s Foreground stage writes this mask to disk and the Segmentation stage feeds it back here, so the territory the walk fills is exactly the one tuned in the Foreground stage (not re-derived from the current knobs). (T, Y, X) for a full-stack run, (Y, X) (or a (T, Y, X) stack sliced at frame) for a single-frame run. foreground_clean is still computed for the cost field’s foreground score regardless.

  • progress_cb (Callable[[str], None] | None) – Receives short status strings.

Return type:

CellDivergenceResult

Submodules

cell_divergence_segmentation

Unary-only cell segmentation from cached divergence maps.

cell_label_icm

Unary-only cell label segmentation (contour-aware geodesic Voronoi).

contour_filtering

Filtering helpers for nucleus contour-map stacks.

lineage

Backward-compatible shim.

nucleus_segmentation

Nucleus segmentation helpers: cancellation and per-label hole filling.