Launching Analysis with Cell Tracking

This guide covers enabling btrack-based cell tracking for lineage analysis and trajectory reconstruction. Tracking extends the basic analysis pipeline to link cells across time points and detect division events.

Overview

Cell tracking in HiTMicTools:

  • Uses the btrack library (Bayesian multi-object tracking)

  • 2D tracking only: Tracks cells in XY plane across time (not 3D/volume tracking)

  • Links segmented cells across time frames

  • Detects cell divisions and apoptosis events

  • Outputs trajectory data with parent-daughter relationships

  • Requires aligned frames for accurate linking

About btrack

HiTMicTools uses btrack for probabilistic tracking based on Bayesian inference. This approach combines spatial information with cell appearance features for robust trajectory linking, even in crowded fields or with temporary occlusions.

Key publications:

  1. Automated Deep Lineage Tree Analysis Ulicna, K., Vallardi, G., Charras, G., & Lowe, A. R. (2021). Automated Deep Lineage Tree Analysis Using a Bayesian Single Cell Tracking Approach. Frontiers in Computer Science, 3, 92. https://doi.org/10.3389/fcomp.2021.734559

  2. Local Cellular Neighborhood and Cell Competition Bove, A., Gradeci, D., Fujita, Y., Banerjee, S., Charras, G., & Lowe, A. R. (2017). Local cellular neighborhood controls proliferation in cell competition. Molecular Biology of the Cell, 28(23), 3215-3228. https://doi.org/10.1091/mbc.E17-06-0368

Note on 3D tracking: While btrack supports 3D/volumetric tracking, HiTMicTools is designed specifically for 2D time-lapse microscopy. All tracking configurations and workflows assume 2D XY tracking across time.

1. Prerequisites

btrack Installation

Version Requirements:

  • Recommended: btrack >= 0.7.0 (install via pip)

  • Minimum compatible: btrack 0.6.6rc1 (requires manual compilation)

  • Not compatible: btrack < 0.6.6rc1 (dependency conflicts with pydantic and ome-types)

Option 2: Manual Compilation (for btrack 0.6.6rc1)

If btrack 0.7.0 is not yet released, or you need version 0.6.6rc1:

# Clone the btrack repository
git clone https://github.com/quantumjot/btrack.git
cd btrack

# Checkout the compatible version
git checkout v0.6.6rc1  # or main for latest development version

# Compile btrack (uses the provided build script)
bash build.sh

# Install the package
pip install .

# Clean up build artifacts (optional)
python setup.py clean --all
cd ..

# Verify installation
python -c "import btrack; print(f'btrack version: {btrack.__version__}')"

Important Notes:

  • Manual compilation requires C++ compiler toolchain

  • Dependency conflicts occur with btrack < 0.6.6rc1 due to pydantic and ome-types version requirements

  • If you encounter installation issues, ensure your build tools are up to date

  • If you installed HiTMicTools via pip and don’t plan to use tracking, you can skip btrack installation

Model Collection with Tracking Support

Ensure your model collection includes tracking configurations:

  • model_collection_tracking_20250529.zip (recommended)

  • Contains pre-configured tracking parameters for typical ASCT workflows

2. Understanding Tracking Configuration

Tracking Configuration Structure

btrack uses a YAML/JSON configuration file that defines:

  1. Motion model: How cells move in 2D (constant velocity model for XY position)

  2. Hypothesis model: Rules for linking, division, and apoptosis

  3. Object model: Appearance-based features for association (area, orientation, etc.)

Default Configuration Example

The default tracking config (CellTrackingConfig) for 2D tracking looks like:

name: MyCellTrackingConfig
version: 0.6.6rc
verbose: false
max_search_radius: 15  # Maximum linking distance in pixels (2D distance)

# Features used for appearance-based association
features:
  - area
  - orientation

# Motion model (constant velocity in 2D)
motion_model:
  name: cell_motion
  dt: 1.0                    # Time step per frame
  measurements: 3            # (x, y, t) - position and time
  states: 6                  # (x, y, t, vx, vy, vt) - position, time, and velocities
  accuracy: 7.5
  prob_not_assign: 0.1       # Probability of missed detection
  max_lost: 5                # Max frames before terminating track

# Hypothesis generation for linking
hypothesis_model:
  name: cell_hypothesis
  hypotheses:
    - P_FP                   # False positive
    - P_init                 # Initialization
    - P_term                 # Termination
    - P_link                 # Linking
    - P_branch               # Division
    - P_dead                 # Apoptosis

  # Key parameters for successful tracking
  lambda_time: 5.0
  lambda_dist: 3.0
  lambda_link: 10.0
  lambda_branch: 50.0
  eta: 1.0e-10
  theta_dist: 25.0
  theta_time: 50.0
  dist_thresh: 25.0          # Distance threshold for linking (pixels)
  time_thresh: 2             # Time threshold (frames)
  apop_thresh: 5             # Apoptosis detection threshold
  segmentation_miss_rate: 0.1
  apoptosis_rate: 0.001
  max_search_radius: 15      # Must match top-level parameter

Critical Parameters for Tuning

When tracking performance is suboptimal, adjust these parameters:

max_search_radius (default: 15)

  • Maximum distance (pixels) a cell can move between frames

  • Too large: Incorrect associations, increased computation

  • Too small: Missed links for fast-moving cells

  • Recommendation: Set to 1.5-2x the typical cell displacement per frame

dist_thresh (default: 25.0)

  • Spatial bin size for hypothesis generation

  • Controls which detections are considered for linking

  • Too large: More false links, slower computation

  • Too small: Breaks tracks for fast-moving cells

  • Recommendation: Slightly larger than max_search_radius

time_thresh (default: 2)

  • Maximum time gap (frames) for linking across missing detections

  • Allows bridging when cells temporarily go out of focus

  • Too large: Links unrelated cells, slower computation

  • Too small: Fragments tracks when cells briefly disappear

  • Recommendation: 2-3 frames for typical time-lapse

segmentation_miss_rate (default: 0.1)

  • Expected rate of missed detections

  • Higher values make tracker more tolerant of gaps

  • Recommendation: 0.05-0.15 based on segmentation quality

apoptosis_rate (default: 0.001)

  • Expected rate of cell death events

  • Too high: Interprets fast movement as death

  • Too low: Doesn’t detect actual apoptosis

  • Recommendation: Adjust based on experimental conditions

3. Pipeline Configuration

Basic Tracking Setup

Add tracking to your analysis config:

input_data:
  input_folder: "./data/experiment_tracking"
  output_folder: "./results/experiment_tracking"
  file_type: ".nd2"
  export_labelled_masks: false
  export_aligned_image: false

pipeline_setup:
  name: "ASCT_focusrestore"
  parallel_processing: true
  num_workers: 2                    # Reduce for tracking (more memory intensive)
  reference_channel: 0
  pi_channel: 1
  focus_correction: true
  align_frames: true                # REQUIRED for tracking
  method: "basicpy_fl"
  tracking: true                    # Enable tracking

models:
  model_collection: "./models/model_collection_tracking_20250529.zip"

tracking:
  parameters_override: null         # Use default config from bundle

Custom Tracking Parameters

Override specific parameters for your experiment:

pipeline_setup:
  tracking: true

tracking:
  parameters_override:
    hypothesis_model:
      max_search_radius: 20.0       # Cells move faster in this experiment
      dist_thresh: 30.0              # Increase accordingly
      time_thresh: 3                 # Allow longer gaps
      segmentation_miss_rate: 0.15   # More permissive for noisy data
      apoptosis_rate: 0.005          # Higher cell death rate

Using a Custom Tracking Config File

Provide a completely custom configuration:

tracking:
  config_path: "./config/my_custom_tracking_config.yaml"
  parameters_override: null

Note: If both config_path and parameters_override are specified, the override is applied to the loaded config.

4. Running Analysis with Tracking

Command

The CLI command is identical to basic analysis:

hitmictools run --config config/tracking_config.yml

Expected Output

The CLI will indicate tracking is enabled:

Loading pipeline: ASCT_focusrestore
Tracking enabled: True
Loading tracking configuration from model bundle
Tracking config: CellTrackingConfig (max_search_radius=15.0)
Processing files...

Processing Notes

  • Tracking is more memory-intensive than basic analysis

  • Reduce num_workers to 2-3 to avoid memory issues

  • Processing time increases ~20-40% with tracking

  • Frame alignment is performed automatically if not already done

5. Understanding Tracking Output

Output Files

results/experiment_tracking/
├── image001_analysis_results.csv          # Main results with tracking data
├── image001_tracking_data_from_pipeline.csv  # Tracking-specific output
└── analysis_logs/
    └── tracking_log.txt

Tracking Columns in CSV

The results CSV includes additional columns:

  • track_id: Unique identifier for each cell trajectory

  • parent_track_id: Parent track (if cell divided from another)

  • root_track_id: Original ancestor track

  • generation: Generation number in lineage tree

  • track_length: Total frames in this track

  • state: Track state (e.g., “interphase”, “dividing”, “apoptotic”)

Lineage Relationships

Parent-daughter relationships:

track_id  parent_track_id  generation
1         0                0           # Original cell
2         1                1           # Daughter of track 1
3         1                1           # Another daughter of track 1
4         2                2           # Granddaughter (from track 2)

6. Validating Tracking Results

Visual Validation

Before processing large datasets, validate tracking on a small subset:

  1. Process 2-3 test movies with export_aligned_image: true

  2. Load aligned images + CSV in ImageJ/napari

  3. Verify tracks follow cells correctly

  4. Check for common issues:

    • Fragmented tracks (increase time_thresh, dist_thresh)

    • Swapped identities (decrease max_search_radius)

    • Missed divisions (adjust lambda_branch)

    • False divisions (increase lambda_branch)

Diagnostic Metrics

Check tracking quality in the output CSV:

import pandas as pd

df = pd.read_csv("results/image001_analysis_results.csv")

# Track length distribution
print(df.groupby('track_id')['frame'].count().describe())

# Division events
divisions = df[df['parent_track_id'] > 0]['parent_track_id'].nunique()
print(f"Division events detected: {divisions}")

# Track fragmentation (too many short tracks)
short_tracks = (df.groupby('track_id')['frame'].count() < 5).sum()
print(f"Short tracks (<5 frames): {short_tracks}")

7. Optimizing Tracking Parameters

Workflow for Parameter Tuning

  1. Start with defaults: Run with parameters_override: null

  2. Visual inspection: Check 2-3 movies with aligned output

  3. Identify issues:

    • Fragmented tracks → increase time_thresh, dist_thresh

    • ID swaps → decrease max_search_radius, dist_thresh

    • Missed divisions → decrease lambda_branch

    • False divisions → increase lambda_branch

  4. Iterate: Adjust one parameter at a time

  5. Validate: Re-run test movies and verify improvement

Parameter Adjustment Guide

Problem

Likely Cause

Solution

Tracks end prematurely

time_thresh too low

Increase to 3-4

Cells swap identities

max_search_radius too large

Decrease by 5-10 pixels

Tracks fragment frequently

dist_thresh too small

Increase to 1.5x max_search_radius

Missed cell divisions

lambda_branch too high

Decrease to 20-30

False division events

lambda_branch too low

Increase to 60-80

Cells not tracked

segmentation_miss_rate too low

Increase to 0.15-0.2

Example Optimized Config

For fast-moving cells with good segmentation:

tracking:
  parameters_override:
    hypothesis_model:
      max_search_radius: 25.0      # Cells move ~20 pixels/frame
      dist_thresh: 35.0
      time_thresh: 2               # Good segmentation, allow short gaps
      apop_thresh: 5
      segmentation_miss_rate: 0.05 # High-quality segmentation
      apoptosis_rate: 0.001

For slow-moving cells with noisy segmentation:

tracking:
  parameters_override:
    hypothesis_model:
      max_search_radius: 10.0      # Cells barely move
      dist_thresh: 15.0
      time_thresh: 4               # Bridge longer gaps
      apop_thresh: 6
      segmentation_miss_rate: 0.2  # Tolerate missed detections
      apoptosis_rate: 0.001

8. Troubleshooting

Common Issues

“btrack not installed”

  • Install btrack >= 0.7.0 via pip: pip install btrack>=0.7.0

  • If version 0.7.0 is unavailable, follow manual compilation steps for 0.6.6rc1

  • Avoid btrack < 0.6.6rc1 (dependency conflicts with pydantic and ome-types)

Tracking produces no tracks

  • Check that align_frames: true in pipeline_setup

  • Verify segmentation is working (check CSV has detections)

  • Increase max_search_radius and dist_thresh

Too many short tracks

  • Increase time_thresh to bridge gaps

  • Increase segmentation_miss_rate to be more permissive

  • Check segmentation quality (may need better models)

Cells swap identities

  • Decrease max_search_radius

  • Decrease dist_thresh

  • Add more features to features list (requires re-training)

False division events

  • Increase lambda_branch (makes divisions less likely)

  • Check segmentation isn’t splitting single cells

Memory errors during tracking

  • Reduce num_workers to 1-2

  • Process files sequentially instead of in parallel

  • Close other applications

Performance Tips

  • Large experiments: Use SLURM workflow (see using SLURM)

  • Memory constraints: Set num_workers: 1 for tracking runs

  • Validation: Always test on 2-3 movies before batch processing

  • Config versioning: Save tuned configs with descriptive names (e.g., tracking_config_fastcells.yml)

9. Advanced Tracking Features

Region of Interest (ROI) Constraints

Constrain tracking to specific imaging regions in the 2D field of view:

# In custom scripts (not via config)
from HiTMicTools.tracking.cell_tracker import CellTracker

tracker = CellTracker(config_path="config.yaml")
tracker.track_objects(
    df=measurements_df,
    volume_bounds=((0, 2048), (0, 2048)),  # (x_min, x_max), (y_min, y_max) in pixels
    logger=logger
)

This is useful when analyzing specific regions of interest or excluding edge artifacts.

Update Methods

btrack supports different update strategies:

  • EXACT: Full Bayesian update (slowest, most accurate)

  • APPROXIMATE: Faster approximation

  • MOTION: Motion-only (fastest)

  • VISUAL: Appearance-only

Specify in config:

tracking:
  parameters_override:
    tracking_updates:
      - MOTION
      - VISUAL

Custom Features

Add custom features for appearance-based tracking (requires model re-training):

features:
  - area
  - orientation
  - eccentricity
  - mean_intensity

Note: Features must be present in the segmentation output CSV.

10. Downstream Analysis

Loading Tracking Data

import pandas as pd
import numpy as np

# Load tracking results
df = pd.read_csv("results/image001_analysis_results.csv")

# Filter by track length
min_frames = 10
long_tracks = df.groupby('track_id').filter(lambda x: len(x) >= min_frames)

# Extract lineage tree
def get_lineage(df, track_id):
    """Get all descendants of a track."""
    descendants = df[df['parent_track_id'] == track_id]['track_id'].unique()
    result = [track_id]
    for desc in descendants:
        result.extend(get_lineage(df, desc))
    return result

# Example: Get all descendants of track 1
lineage_1 = get_lineage(df, track_id=1)
print(f"Track 1 lineage: {lineage_1}")

Visualization

Using matplotlib:

import matplotlib.pyplot as plt

# Plot trajectories
fig, ax = plt.subplots(figsize=(10, 10))

for track_id in df['track_id'].unique():
    track_data = df[df['track_id'] == track_id]
    ax.plot(track_data['centroid_1'], track_data['centroid_0'],
            alpha=0.7, linewidth=2)

ax.set_xlabel('X position (pixels)')
ax.set_ylabel('Y position (pixels)')
ax.set_title('Cell Trajectories')
plt.show()

Export for External Tools

Export to formats compatible with other analysis tools:

# For Trackmate/ImageJ
trackmate_format = df[['track_id', 'frame', 'centroid_0', 'centroid_1', 'area']]
trackmate_format.columns = ['TRACK_ID', 'FRAME', 'POSITION_Y', 'POSITION_X', 'AREA']
trackmate_format.to_csv("trackmate_compatible.csv", index=False)

Summary

Cell tracking in HiTMicTools:

  • 2D tracking only: Designed for XY plane tracking across time (not 3D/volumetric)

  • Requires btrack >= 0.7.0 (or 0.6.6rc1 with manual compilation)

  • Based on Bayesian inference for robust trajectory linking

  • Uses model collections with pre-configured parameters

  • Outputs comprehensive lineage data with parent-daughter relationships

  • Requires parameter tuning for optimal performance

  • Best validated on test data before batch processing

Key References:

  • Ulicna et al. (2021) - Automated Deep Lineage Tree Analysis. Front. Comput. Sci.

  • Bove et al. (2017) - Local cellular neighborhood controls proliferation. Mol. Biol. Cell

For cluster-scale tracking analyses, see the SLURM guide.