Source code for itasc.tracking_ultrack.config
"""Pydantic configuration model for the Ultrack-based tracking stage."""
from __future__ import annotations
from multiprocessing import cpu_count
from pydantic import BaseModel
[docs]
class TrackingConfig(BaseModel):
# Node area filters (applied before NodeDB insert)
min_area: int = 100
max_area: int = 1_000_000
# ID scheme — must match ultrack._generate_id
max_segments_per_time: int = 1_000_000
# Atom extraction (stage ①) — see atoms.AtomParams
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
# Atom-union candidate generation (stage ②)
# Backbone merge tree (always built) + branch candidates admitted
# most-ambiguous-first up to a single per-frame overlap-pair budget.
# The budget is the one branching knob: 0 → nested hierarchy, large →
# full lattice. ``atom_union_max_area`` stays a hard physical cap on any
# candidate union. ``atom_union_max_atoms`` is removed — union depth is
# governed by the area cap and the maximal-merge-always guarantee.
atom_union_max_area: int = 8000
atom_overlap_budget: int = 300_000
# Linking
# Ultrack's multiprocessing_apply activates a Pool only when n_workers > 1,
# and batch_index_range uses n_workers as a window stride (0 would div-zero).
# Default to min(cpu_count(), 8) for automatic parallelism up to 8 threads.
max_distance: float = 15.0
max_neighbors: int = 5
distance_weight: float = 0.05
link_n_workers: int = min(cpu_count(), 8)
linking_mode: str = "default" # "default" or "shape"
area_weight: float = 1.0
iou_weight: float = 1.0
min_link_iou: float = 0.1
min_area_ratio: float = 0.3
# Solver / ILP
appear_weight: float = -0.001
disappear_weight: float = -0.001
division_weight: float = -0.001
link_function: str = "power"
power: int = 4
bias: float = 0.0
solution_gap: float = 0.001
time_limit: int = 36000
window_size: int = 0 # 0 = solve all at once
# Segmentation (ultrack.segment / ultrack.core.segmentation.processing.segment)
seg_min_area: int = 300
seg_max_area: int = 100_000
seg_foreground_threshold: float = 0.5
seg_min_frontier: float = 0.0
seg_ws_hierarchy: str = "area" # "area", "dynamics", or "volume"
seg_n_workers: int = 1
# Resolve-from-validated node prior
quality_weight: float = 1.0
quality_exponent: float = 8.0
circularity_weight: float = 0.25
# Per-frame correction primitives
anchor_radius_px: float = 15.0
anchor_stamp_radius_px: float = 15.0