traccuracy.loaders._napari
Module Contents
Functions
|
Load a napari Tracks layer into a TrackingGraph. |
- traccuracy.loaders._napari.load_napari_data(data: numpy.ndarray, graph: collections.abc.Mapping[int, collections.abc.Sequence[int]] | None = None, properties: collections.abc.Mapping[str, collections.abc.Sequence] | None = None, segmentation: numpy.ndarray | None = None, seg_id_key: str | None = None, name: str | None = None, progbar_class: type[tqdm.tqdm] = tqdm) traccuracy._tracking_graph.TrackingGraph[source]
Load a napari Tracks layer into a TrackingGraph.
A napari Tracks layer stores one row per detection in
datawith columns[track_id, t, (z), y, x], and encodes track lineage ingraphas{child_track_id: [parent_track_id, ...]}. This loader turns that into aTrackingGraphso it can be matched/evaluated, mirroringload_point_data()but for the in-memory napari format.Edges are built two ways: consecutive detections of the same
track_id(ordered by time) are connected, and each parent track’s last detection is connected to each child track’s first detection fromgraph.This function takes plain arrays/dicts (the
.data/.graph/.propertiesof a napari Tracks layer) rather than a layer object, so traccuracy does not depend on napari.To match tracks to a
segmentationthere are two modes:Implicit (default): per frame, detections are matched to segmentation masks by optimal bipartite assignment between detection positions and mask centers of mass (minimizing total Euclidean distance), and each detection takes its matched mask’s label. This does not require points to sit inside their own mask. Just pass
segmentation. A frame with fewer masks than detections raises an error (some detection cannot be matched).Explicit: the label for each detection is taken from a precomputed
propertiescolumn. Passsegmentationtogether withseg_id_keynaming that column. Use this when you already know the labels.
Example
A napari
Trackslayer exposes its contents as three plain attributes; pass those straight in (no napari import needed on the traccuracy side):# `tracks_layer` is a napari Tracks layer (viewer.add_tracks(...)) tg = load_napari_data( data=tracks_layer.data, # (N, 2+D) [track_id, t, (z), y, x] graph=tracks_layer.graph, # {child_track_id: [parent_track_id]} properties=tracks_layer.properties, )
If you have the raw arrays instead of a layer, build them by hand. Here track 1 spans frames 0-1 and divides into tracks 2 and 3 at frame 2:
import numpy as np data = np.array( [ [1, 0, 10, 20], # track 1, t=0 [1, 1, 11, 21], # track 1, t=1 [2, 2, 12, 22], # track 2, t=2 (child of 1) [3, 2, 8, 18], # track 3, t=2 (child of 1) ] ) graph = {2: [1], 3: [1]} tg = load_napari_data(data, graph=graph)
To enable segmentation-based matching, pass a
segmentationarray. By default each detection is matched implicitly to the nearest mask centroid per frame, so no extra bookkeeping is needed:tg = load_napari_data( data, graph=graph, segmentation=segmentation, # (T, (Z), Y, X) )
If you already have the label ids precomputed (e.g. positions don’t sit cleanly inside their masks), match explicitly instead by passing the
propertieskey that holds them:tg = load_napari_data( data, graph=graph, properties={"label": [11, 12, 13, 14]}, segmentation=segmentation, # (T, (Z), Y, X), label ids match above seg_id_key="label", )
- Parameters:
data (np.ndarray) – The napari Tracks layer
data, shape(N, 2 + D)with columns[track_id, t, (z), y, x].Dis 2 or 3.graph (Mapping[int, Sequence[int]] | None, optional) – The napari Tracks
graph, mapping each child track id to its parent track id(s). The parent may be a bare int or a list. Defaults to None (no divisions).properties (Mapping[str, Sequence] | None, optional) – Per-detection properties (same length/order as
datarows), e.g. the napari Tracks layerproperties. Only read whenseg_id_keyis given, to look up precomputed segmentation label ids. Defaults to None.segmentation (np.ndarray | None, optional) – Segmentation array of shape
(T, (Z), Y, X). When given, each node carries asegmentation_idfor segmentation-based matching. Unlessseg_id_keyis also given, each detection is matched implicitly to the nearest mask centroid per frame. Defaults to None.seg_id_key (str | None, optional) – Key in
propertiesholding each detection’s precomputed segmentation label id. Pass this to match explicitly instead of matching detections to mask centroids. Requiressegmentation. Defaults to None.name (str | None, optional) – Optional name for the dataset. Defaults to None.
progbar_class (optional) – tqdm-compatible class wrapping the per-frame implicit-matching loop. Pass e.g.
napari.utils.progressto show the bar in napari’s activity dock; defaults to plaintqdm(terminal).
- Raises:
ValueError – data does not have shape (N, 2 + D) with D in {2, 3}.
ValueError – track ids (column 0) or times (column 1) are not integer-valued.
ValueError – duplicate (track_id, t) rows (ambiguous within-track edges).
ValueError – seg_id_key given without segmentation.
ValueError – seg_id_key not present in properties, its length does not match the number of detections, or its values are not integer-valued.
ValueError – (implicit matching) segmentation dims don’t match the data, a frame has fewer masks than detections (some detection cannot be matched), or two detections in a frame resolve to the same label.
- Returns:
TrackingGraph