traccuracy.loaders

Subpackage for loading tracking data into memory

This subpackage contains functions for loading ground truth or tracking method outputs into memory as TrackingGraph objects. Each loading function must return one TrackingGraph object which has a track graph and optionally contains a corresponding segmentation.

Package Contents

Functions

load_ctc_data(→ traccuracy._tracking_graph.TrackingGraph)

Read the CTC segmentations and track file and create a TrackingGraph.

load_tiffs(→ numpy.ndarray)

Load a directory of individual frames into a stack.

load_geff_data(→ traccuracy._tracking_graph.TrackingGraph)

Load a graph into memory from a geff file

load_napari_data(...)

Load a napari Tracks layer into a TrackingGraph.

load_point_data(, time_column, seg_id_column, name, sep)

Load point-based tracking data into a TrackingGraph from a csv-like file

traccuracy.loaders.load_ctc_data(data_dir: str, track_path: str | None = None, name: str | None = None, run_checks: bool = True, border_margin: float | None = None) traccuracy._tracking_graph.TrackingGraph[source]

Read the CTC segmentations and track file and create a TrackingGraph.

Parameters:
  • data_dir (str) – Path to directory containing CTC tiffs.

  • track_path (optional, str) – Path to CTC track file. If not passed, finds *_track.txt in data_dir.

  • name (optional, str) – Name of data to store in TrackingGraph

  • run_checks (optional, bool) – If set to True (default), runs checks on the data to ensure valid CTC format.

  • border_margin (float, optional) – If set, nodes whose centroid is within this distance (in pixels) of the spatial border will be excluded from the graph. Defaults to None (no filtering).

Returns:

TrackingGraph object containing segmentations and graph.

Return type:

traccuracy.TrackingGraph

Raises:

ValueError – If the tracks file is not found. If run_checks is True, whenever any of the CTC format checks are violated. If run_checks is False, whenever any other Exception occurs while creating the graph.

traccuracy.loaders.load_tiffs(data_dir: str) numpy.ndarray[source]

Load a directory of individual frames into a stack.

Parameters:

data_dir (str) – Path to directory of tiff files

Raises:

FileNotFoundError – No tif files found in data_dir

Returns:

4D array with dims TYXC

Return type:

np.array

traccuracy.loaders.load_geff_data(geff_path: str, load_geff_seg: bool = False, seg_path: str | None = None, seg_property: str | None = None, name: str | None = None, load_all_props: bool = False, border_margin: float | None = None) traccuracy._tracking_graph.TrackingGraph[source]

Load a graph into memory from a geff file

Segmentations can be optionally loaded either from a related object specified in the geff (load_geff_seg=True) or with a path to a zarr array seg_path and seg_property. If loading graphs with flags, e.g. for visualization, pass load_all_props=True.

Parameters:
  • geff_path (str) – Path to a geff group inside of a zarr,

  • load_geff_seg (bool, optional) – Load segmentation based on a geff metadata of related segmentation. Defaults to False.

  • seg_path (str | None, optional) – Path to a zarr array containing segmentation data. We assume that the axes order in your segmentation array matches the axes in your geff. If this is not true please load the segmentation yourself and add it to TrackingGraph.segmentation. Defaults to None.

  • seg_property (str | None, optional) – If seg_path provided, this is the corresponding property on the geff graph that contains the segmentation key. Defaults to None.

  • name (str | None, optional) – Optional name to store on TrackingGraph for identification. Defaults to None.

  • load_all_props (bool, optional) – If True, load all node and edge properties on the graph. Defaults to False and only spatiotemporal and segmentation node properties are loaded. Set to True to get already annotated error flags, e.g. for visualization.

  • border_margin (float, optional) – If set, nodes whose centroid is within this distance (in pixels) of the spatial border will be excluded from the graph. Requires segmentation to be loaded. Defaults to None (no filtering).

traccuracy.loaders.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 data with columns [track_id, t, (z), y, x], and encodes track lineage in graph as {child_track_id: [parent_track_id, ...]}. This loader turns that into a TrackingGraph so it can be matched/evaluated, mirroring load_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 from graph.

This function takes plain arrays/dicts (the .data / .graph / .properties of a napari Tracks layer) rather than a layer object, so traccuracy does not depend on napari.

To match tracks to a segmentation there 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 properties column. Pass segmentation together with seg_id_key naming that column. Use this when you already know the labels.

Example

A napari Tracks layer 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 segmentation array. 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 properties key 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]. D is 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 data rows), e.g. the napari Tracks layer properties. Only read when seg_id_key is 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 a segmentation_id for segmentation-based matching. Unless seg_id_key is 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 properties holding each detection’s precomputed segmentation label id. Pass this to match explicitly instead of matching detections to mask centroids. Requires segmentation. 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.progress to show the bar in napari’s activity dock; defaults to plain tqdm (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

traccuracy.loaders.load_point_data(path: str | None = None, df: pandas.DataFrame | None = None, parent_column: str = 'parent', id_column: str = 'node_id', pos_columns: tuple[str, Ellipsis] = ('z', 'y', 'x'), time_column: str = 't', seg_id_column: str | None = None, name: str | None = None, sep: str | None = None) traccuracy._tracking_graph.TrackingGraph[source]

Load point-based tracking data into a TrackingGraph from a csv-like file

Assumes each row contains:

  • time

  • position, e.g. three columns ‘z’, ‘y’, ‘x’

  • parent, a reference to the node in the previous time frame. A node without a parent can be indicated by -1

Parameters:
  • path (str | None, optional) – Path to the csv-like file to load. Defaults to None.

  • df (pd.DataFrame | None, optional) – A dataframe that has already been loaded. Defaults to None.

  • parent_column (str | None, optional) – A reference to the parent node in the previous time frame. Defaults to “parent”.

  • id_column (str, optional) – Column used to specify node ids. Node IDs should be unique positive integers. Defaults to ‘node_id’

  • pos_columns (tuple[str], optional) – A tuple of columns to use for position. Defaults to (“z”, “y”, “x”).

  • time_column (str, optional) – The column to use for time. Defaults to “t”.

  • seg_id_column (str | None, optional) – Name of an optional column containing a segmentation label id. Defaults to None.

  • name (str | None, optional) – Optional string to name/describe the dataset. Defaults to None.

  • sep (str | None, optional) – Passed to pd.read_csv to set the sep kwarg. Defaults to None.

Raises:
  • ValueError – Must provide either a path or a dataframe

  • ValueError – parent_column not present in data

  • ValueError – id_column not present in data

  • ValueError – id_column does not contain positive integers

  • ValueError – id_column does not contain unique values

  • ValueError – pos_columns not present in data

  • ValueError – time_column not present in data

  • ValueError – seg_id_column not present in data

Returns:

TrackingGraph