itasc.tracking_ultrack.atoms

Atom extraction: residual-conditioned foreground split by contour ridges.

Stage ① of the atom-based candidate pipeline. Pure, deterministic functions shared by the interactive preview and the full-stack atoms.tif writer.

Functions

atom_adjacency(atoms)

Region-adjacency graph of a label image: labels sharing a 4-connected border.

atom_adjacency_weighted(atoms, residual_contour)

Atom RAG plus the mean ridge strength on each shared border.

branch_unions(adj, weights, areas, backbone, ...)

Alternative connected unions the backbone did not take, admitted most-ambiguous-first up to the per-frame overlap budget.

build_atom_merge_tree(adj, weights, areas, ...)

Backbone watershed-style merge tree over the atom RAG (always built).

enum_connected_unions(adj, areas, max_atoms, ...)

All connected atom-subsets of size 1..max_atoms with total area ≤ max_area.

extract_atoms_frame(residual_contour, ...)

Split territory into atoms along the cleaned contour ridge.

extract_atoms_stack(fg, contour, params)

Atom label stack for a (T, Y, X) foreground + contour pair.

extract_atoms_stack_with_maps(fg, contour, ...)

(atoms, territory, residual_foreground, residual_contour, ridge) stacks, each (T, Y, X).

params_fingerprint(params)

Stable SHA-1 of the params, used to detect stale atoms.tif in DB-Gen.

read_atoms_params(path)

Return (params_dict, fingerprint) embedded by write_atoms_tif, or (None, None) if the file has no atom metadata.

write_atoms_tif(path, atoms, params)

Write the atom label stack with the params + fingerprint embedded in the TIFF ImageDescription, so DB-Gen (②) can read what produced it.

Classes

AtomParams([fg_window, fg_cutoff, ...])

The knobs that fully determine an atom segmentation.

BranchReport([admitted, skipped, budget_hit])

How branch admission used the per-frame overlap budget.

class itasc.tracking_ultrack.atoms.AtomParams(fg_window=51, fg_cutoff=0.002, fg_strength=1.0, contour_window=51, contour_floor=0.01, contour_strength=1.0, atom_min_area=100)[source]

Bases: object

The knobs that fully determine an atom segmentation.

Parameters:
fg_window: int = 51
fg_cutoff: float = 0.002
fg_strength: float = 1.0
contour_window: int = 51
contour_floor: float = 0.01
contour_strength: float = 1.0
atom_min_area: int = 100
itasc.tracking_ultrack.atoms.extract_atoms_frame(residual_contour, territory, contour_floor, atom_min_area)[source]

Split territory into atoms along the cleaned contour ridge.

ridge is where the residual contour exceeds contour_floor (a noise cutoff). Cores (ridge-free territory) seed a watershed that floods the residual-contour elevation, so a broken faint ridge still meets at the crest. Atoms smaller than atom_min_area are merged into the neighbouring atom they share the longest border with (see _merge_small_atoms); an atom that touches no other label is kept as-is, so no territory pixel is ever blanked.

Returns (atoms, ridge): atoms is the int32 label image; ridge is the boolean wall residual_contour > contour_floor returned as uint8 (Y, X) — the exact array the watershed carves out of territory, surfaced so it can be tuned against directly. Small-atom merging only relabels pixels, so it does not move the ridge.

Return type:

tuple[ndarray, ndarray]

Parameters:
itasc.tracking_ultrack.atoms.extract_atoms_stack_with_maps(fg, contour, params)[source]

(atoms, territory, residual_foreground, residual_contour, ridge) stacks, each (T, Y, X).

ridge is the per-frame residual_contour > contour_floor wall returned by extract_atoms_frame, accumulated as a uint8 stack.

Return type:

tuple[ndarray, ndarray, ndarray, ndarray, ndarray]

Parameters:
itasc.tracking_ultrack.atoms.extract_atoms_stack(fg, contour, params)[source]

Atom label stack for a (T, Y, X) foreground + contour pair.

Per frame: residual the fg map and threshold it into territory, residual the contour map into the watershed elevation, then extract_atoms_frame. Returns the atom labels only — the residual maps are internal.

Return type:

ndarray

Parameters:
itasc.tracking_ultrack.atoms.params_fingerprint(params)[source]

Stable SHA-1 of the params, used to detect stale atoms.tif in DB-Gen.

Return type:

str

Parameters:

params (AtomParams)

itasc.tracking_ultrack.atoms.write_atoms_tif(path, atoms, params)[source]

Write the atom label stack with the params + fingerprint embedded in the TIFF ImageDescription, so DB-Gen (②) can read what produced it.

Return type:

None

Parameters:
itasc.tracking_ultrack.atoms.atom_adjacency(atoms)[source]

Region-adjacency graph of a label image: labels sharing a 4-connected border.

Return type:

dict[int, set[int]]

Parameters:

atoms (ndarray)

itasc.tracking_ultrack.atoms.atom_adjacency_weighted(atoms, residual_contour)[source]

Atom RAG plus the mean ridge strength on each shared border.

Returns (adj, weights) where adj is the same region-adjacency graph as atom_adjacency(), and weights maps each (u, v) edge (u < v) to the mean residual_contour value on the 4-connected wall separating the two atoms — the saliency of that wall. This is the per-edge ridge weight the merge tree merges across and the branch admission orders by.

The wall value of a border pixel-pair (p u, q v) is the mean of the residual-contour at p and q (the elevation the watershed floods to join them); the edge weight is the mean over all such pairs.

Return type:

tuple[dict[int, set[int]], dict[tuple[int, int], float]]

Parameters:
itasc.tracking_ultrack.atoms.build_atom_merge_tree(adj, weights, areas, *, min_area, max_area, min_frontier)[source]

Backbone watershed-style merge tree over the atom RAG (always built).

A binary partition tree by altitude: atoms are leaves, and edges (walls) are consumed in ascending ridge weight — weakest wall first — each merge creating an internal node = the union of the two regions it joins. Per connected component the leaves are the atoms and the root is the maximal connected merge; every node is a candidate. Because the structure is a tree, any two nodes are nested or disjoint, so overlaps among backbone nodes are ancestor↔descendant only (linear, not quadratic).

This is the same shape of hierarchy ultrack builds at the pixel level (hg.watershed_hierarchy_by_* + min_area / max_area / min_frontier pruning), but with atoms — the agreed stage-① primitive — as leaves, implemented here without a higra dependency on the candidate path.

Pruning: singletons (atoms) are always kept; an internal node is kept only when min_area area max_area and the wall joining it to its sibling (its parent merge’s frontier) is min_frontier — a sub-threshold wall is a non-salient split, collapsed into the parent. Returns the kept candidate members as frozensets, singletons first.

Return type:

list[frozenset[int]]

Parameters:
class itasc.tracking_ultrack.atoms.BranchReport(admitted=0, skipped=0, budget_hit=False)[source]

Bases: object

How branch admission used the per-frame overlap budget.

Parameters:
admitted: int = 0
skipped: int = 0
budget_hit: bool = False
itasc.tracking_ultrack.atoms.branch_unions(adj, weights, areas, backbone, *, max_area, overlap_budget)[source]

Alternative connected unions the backbone did not take, admitted most-ambiguous-first up to the per-frame overlap budget.

Best-first growth over the atom RAG enumerates connected unions (area ≤ max_area) in ascending bottleneck wall weight — the strongest wall that must be crossed to form the union, i.e. how near-tied its weakest internal split is. A near-tie is a coin-flip the tree may have gotten wrong; a strong wall is a confident separation. Singletons and backbone nodes are skipped (they are already candidates) but still expanded.

Budget: admitting a candidate over atoms S adds Σ_{a∈S} k_a new overlap pairs, where k_a is how many already-kept candidates contain atom a (initialised from the backbone, so branch↔backbone overlaps are charged; the backbone↔backbone floor is free). A running total is kept and admission stops the moment the next candidate would cross overlap_budget — most-ambiguous-first, no overshoot. overlap_budget → 0 admits nothing (pure backbone); overlap_budget → large exhausts the lattice.

Returns (admitted_members, report).

Return type:

tuple[list[frozenset[int]], BranchReport]

Parameters:
itasc.tracking_ultrack.atoms.enum_connected_unions(adj, areas, max_atoms, max_area)[source]

All connected atom-subsets of size 1..max_atoms with total area ≤ max_area.

BFS growth with a global seen set — each subset is reached exactly once, deduped by frozenset. This is the full lattice (the overlap_budget → large limit of build_atom_merge_tree() + branch_unions()); it explodes on dense frames, so it is retained as the equivalence reference for tests, not the default candidate-generation path.

Return type:

list[frozenset[int]]

Parameters:
itasc.tracking_ultrack.atoms.read_atoms_params(path)[source]

Return (params_dict, fingerprint) embedded by write_atoms_tif, or (None, None) if the file has no atom metadata.

Return type:

tuple[dict | None, str | None]