itasc.tracking_ultrack.corrections

Per-frame correction primitives for Ultrack solves and exports.

Functions

annotate_anchor_tail_links(working_dir, ...)

Force best predecessor and successor links around anchored tracks.

apply_corrections_to_database(working_dir, ...)

Apply solve-time correction annotations to data.db.

apply_post_solve_corrections(...[, working_dir])

Apply anchor remap/stamp and validated paste-back to exported labels.

corrections_from_validated_tracks(...)

Convert the legacy validated-track store to validated corrections.

ensure_anchor_incident_links(working_dir, cfg)

Insert missing LinkDB rows for edges incident to anchor (REAL) nodes.

inject_unmatched_anchor_nodes(working_dir, ...)

Insert REAL NodeDB rows for anchor corrections that had no existing candidate.

Classes

AnchorIncidentLinkReport([inserted, ...])

AnchorTailLinkReport([annotated, ...])

Correction(cell_id, t, kind, y, x)

CorrectionDatabaseReport([fake_nodes, ...])

HomemadeAnchorInjectionReport([injected, ...])

PostSolveCorrectionReport([...])

class itasc.tracking_ultrack.corrections.Correction(cell_id, t, kind, y, x)[source]

Bases: object

Parameters:
cell_id: int
t: int
kind: Literal['validated', 'anchor']
y: float
x: float
class itasc.tracking_ultrack.corrections.CorrectionDatabaseReport(fake_nodes=0, anchor_nodes=0, anchor_links=0, anchor_overlaps_pruned=0, unmatched_anchors=())[source]

Bases: object

Parameters:
fake_nodes: int = 0
anchor_nodes: int = 0
anchor_overlaps_pruned: int = 0
unmatched_anchors: tuple[Correction, ...] = ()
class itasc.tracking_ultrack.corrections.AnchorIncidentLinkReport(inserted=0, anchors_processed=0)[source]

Bases: object

Parameters:
  • inserted (int)

  • anchors_processed (int)

inserted: int = 0
anchors_processed: int = 0
class itasc.tracking_ultrack.corrections.AnchorTailLinkReport(annotated=0, skipped_no_anchor=0, skipped_no_link=0)[source]

Bases: object

Parameters:
  • annotated (int)

  • skipped_no_anchor (int)

  • skipped_no_link (int)

annotated: int = 0
skipped_no_anchor: int = 0
class itasc.tracking_ultrack.corrections.PostSolveCorrectionReport(remapped_anchor_tracks=0, stamped_anchors=0, pasted_validated=0)[source]

Bases: object

Parameters:
  • remapped_anchor_tracks (int)

  • stamped_anchors (int)

  • pasted_validated (int)

remapped_anchor_tracks: int = 0
stamped_anchors: int = 0
pasted_validated: int = 0
itasc.tracking_ultrack.corrections.corrections_from_validated_tracks(validated_tracks, tracked_labels)[source]

Convert the legacy validated-track store to validated corrections.

Return type:

list[Correction]

Parameters:
itasc.tracking_ultrack.corrections.apply_corrections_to_database(working_dir, corrections, cfg, *, annotate_anchor_links=True, tracked_labels=None)[source]

Apply solve-time correction annotations to data.db.

Validated frames mark nearby candidates FAKE. Anchors mark the nearest surviving candidate REAL and mark consecutive anchor links REAL. In Ultrack 0.6.x these are hard annotations when solve uses use_annotations=True.

tracked_labels enables IoU-based candidate matching for anchors. When provided, the mask of the anchored cell in tracked_labels is compared against NodeDB candidate masks, and the candidate with the highest IoU is chosen. This correctly identifies the intended candidate even when two hierarchical candidates (e.g. parent vs child) have nearly identical centroids. Falls back to centroid-distance matching when no IoU > 0 is found.

Return type:

CorrectionDatabaseReport

Parameters:

Insert missing LinkDB rows for edges incident to anchor (REAL) nodes.

The linker keeps only the top cfg.max_neighbors source-side edges per target. A node the user selects as an anchor after solving may have been pruned out of LinkDB entirely for some — or all — adjacent-frame candidates, leaving the solver no way to extend the track from it. This fills those gaps for anchor-incident edges, using the same per-pair weight formula as the active linker mode.

Return type:

AnchorIncidentLinkReport

Parameters:

Force best predecessor and successor links around anchored tracks.

Consecutive anchor links constrain only the user-confirmed frames. This helper walks the best positive same-linker chain backward from the first anchor and forward from the last anchor of each cell, mirroring the greedy extender while still letting the ILP handle conflicts with other annotated cells.

Return type:

AnchorTailLinkReport

Parameters:
class itasc.tracking_ultrack.corrections.HomemadeAnchorInjectionReport(injected=0, skipped_no_mask=0, skipped_overflow=0)[source]

Bases: object

Parameters:
  • injected (int)

  • skipped_no_mask (int)

  • skipped_overflow (int)

injected: int = 0
skipped_no_mask: int = 0
skipped_overflow: int = 0
itasc.tracking_ultrack.corrections.inject_unmatched_anchor_nodes(working_dir, unmatched_anchors, tracked_labels, cfg)[source]

Insert REAL NodeDB rows for anchor corrections that had no existing candidate.

Called when apply_corrections_to_database found no NodeDB node within anchor_radius_px for one or more anchor corrections. This happens when the user anchors a manually-drawn cell that the segmenter never produced a candidate for. We extract the cell’s mask from tracked_labels and insert a synthetic NodeDB row marked REAL so the ILP is forced to include it, then add OverlapDB rows with any spatially overlapping existing nodes so the ILP cannot simultaneously select conflicting candidates.

Return type:

HomemadeAnchorInjectionReport

Parameters:
itasc.tracking_ultrack.corrections.apply_post_solve_corrections(exported_labels, corrections, tracked_labels, cfg, *, working_dir=None)[source]

Apply anchor remap/stamp and validated paste-back to exported labels.

Return type:

tuple[ndarray, PostSolveCorrectionReport]

Parameters: