trackpy-particle-tracking
Python library for single-particle tracking (SPT) in video microscopy via the Crocker-Grier algorithm. Locate particles (fluorescent spots, colloids, vesicles, cells) per frame, link into trajectories, filter short tracks, and compute MSD for diffusion analysis.
Install / Use
npx skills add jaechang-hits/SciAgent-Skills --skill trackpy-particle-trackingInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
MarketingSupported Platforms
Our assessment of trackpy-particle-tracking
trackpy-particle-tracking scores 91/100 on our quality scale, 209th of 606 Marketing skills we index (top 35%).
Its SKILL.md is 26 KB long, well organised into 76 sections with 18 code examples: a thorough specification that gives an agent plenty to work with.
It has 367 GitHub stars, a meaningful sign that others use it.
Maintenance, license and trust
- The repository was last updated 37 days ago, so trackpy-particle-tracking is actively maintained.
- No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
- Its trust signals score 88/100, with 1 caution from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Safety scan
No issues foundOur scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.
Automated pattern scan on 2026-10-05. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.
trackpy-particle-tracking compared with similar skills
All 4 of these similar skills score higher than trackpy-particle-tracking; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| trackpy-particle-tracking (this skill)by jaechang-hits | 91 | 367 | 37d ago | SKILL.md |
| Agent-Reachby Panniantong | 100 | 90.8k | 19d ago | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 74.4k | today | CLAUDE.md |
| Scraplingby D4Vinci | 100 | 85.7k | today | MCP Server |
| crawl4aiby unclecode | 100 | 84.8k | 9d ago | MCP Server |
Frequently asked questions
- How do I install trackpy-particle-tracking?
- Run
npx skills add jaechang-hits/SciAgent-Skills --skill trackpy-particle-tracking. The install tabs above show the steps for each supported agent. - Which AI agents does trackpy-particle-tracking work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is trackpy-particle-tracking safe to use?
- Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It declares no license and scores 88/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is trackpy-particle-tracking still maintained?
- The repository was last updated 37 days ago, so trackpy-particle-tracking is actively maintained.
Skill content
View source on GitHubname: "trackpy-particle-tracking" description: "Python library for single-particle tracking (SPT) in video microscopy via the Crocker-Grier algorithm. Locate particles (fluorescent spots, colloids, vesicles, cells) per frame, link into trajectories, filter short tracks, and compute MSD for diffusion analysis. 2D/3D with subpixel accuracy; reads TIF stacks, AVI, image series via pims. Use for quantitative SPT and diffusion coefficient extraction from fluorescence or brightfield video." license: "BSD-3-Clause"
trackpy
Overview
trackpy is a Python library for single-particle tracking (SPT) in video microscopy. It implements the Crocker-Grier algorithm to locate bright spots in each frame with subpixel precision, then links those positions across frames into continuous trajectories. From trajectories, trackpy computes mean squared displacement (MSD), diffusion coefficients, and motion classifications (confined, normal, directed). It handles 2D fluorescence videos, 3D confocal z-stacks, and large image sequences via memory-efficient streaming through the pims image reader library.
When to Use
- You have a fluorescence microscopy video of labeled particles (quantum dots, fluorescent beads, vesicles, receptors) and need to extract individual trajectories and diffusion coefficients.
- You want to measure particle mobility: compute MSD curves and distinguish Brownian diffusion, directed motion, or confined motion from single-particle tracks.
- You are analyzing colloid dynamics, lipid membrane diffusion, intracellular cargo transport, or virus-cell interactions where you need per-particle trajectory data.
- You need 3D tracking from confocal z-stack time series to capture out-of-plane motion of particles or organelles.
- You want to apply drift correction to remove stage drift before computing intrinsic particle motion statistics.
- You need ensemble MSD averaged across hundreds of tracks to extract population-level diffusion behavior with statistical power.
- Use
TrackMate(Fiji/ImageJ plugin) instead when you need a graphical interface, manual curation of tracks, or integration with biological object segmenters (Cellpose, StarDist). - Use
napariwithnapari-trackpyinstead when you want interactive visualization and manual editing of trajectories alongside image data.
Prerequisites
- Python packages:
trackpy,pims,pandas,numpy,matplotlib,scipy - Data requirements: Grayscale or single-channel image sequence (TIF stack, AVI, or directory of PNG/TIF frames); particles should appear as bright Gaussian spots on a darker background (or use
invert=Truefor dark spots on bright background) - Environment: Works in Jupyter notebooks and scripts;
pimshandles most microscopy formats; for ND2 or CZI files installpims-nd2oraicsimageio
pip install trackpy pims pandas numpy matplotlib scipy
# For reading multi-channel or proprietary formats:
pip install pims[bioformats] # Bioformats via JPype
pip install aicsimageio # ND2, CZI, LIF via AICSImageIO
Quick Start
import trackpy as tp
import pims
# Load a TIF image stack (T frames × Y × X)
frames = pims.open("particles.tif") # shape: (T, Y, X)
# Locate particles in all frames
f = tp.batch(frames, diameter=11, minmass=500)
print(f"Found {len(f)} particle detections across {f['frame'].nunique()} frames")
# Link into trajectories
t = tp.link(f, search_range=5, memory=3)
# Remove short-lived tracks (fewer than 10 frames)
t = tp.filter_stubs(t, threshold=10)
print(f"Retained {t['particle'].nunique()} trajectories")
# Compute ensemble MSD
imsd = tp.imsd(t, mpp=0.16, fps=10) # mpp: microns per pixel, fps: frames per second
print(imsd.head())
Core API
Module 1: tp.locate() — Single-Frame Particle Detection
tp.locate() finds bright circular features in one image frame using a bandpass filter followed by local maximum detection. It returns a DataFrame with subpixel x/y positions, integrated mass, signal, and eccentricity for each detected particle.
import trackpy as tp
import pims
import matplotlib.pyplot as plt
frames = pims.open("particles.tif")
frame0 = frames[0] # single 2D array
# Locate particles: diameter must be odd integer, roughly matching spot size in pixels
f0 = tp.locate(frame0, diameter=11, minmass=300, maxsize=None, separation=None)
print(f"Detected {len(f0)} particles in frame 0")
print(f0[['x', 'y', 'mass', 'size', 'ecc']].head())
# x, y: subpixel centroid; mass: integrated brightness; size: Gaussian width; ecc: eccentricity (0=circular)
# Diagnostic plot: annotate detected particles on the raw frame
fig, ax = plt.subplots(figsize=(8, 8))
tp.annotate(f0, frame0, ax=ax, imshow_style={"cmap": "gray"})
ax.set_title(f"Frame 0: {len(f0)} particles detected")
plt.tight_layout()
plt.savefig("locate_diagnostic.png", dpi=150)
print("Saved locate_diagnostic.png")
Module 2: tp.batch() — Multi-Frame Detection
tp.batch() applies tp.locate() to every frame in an image sequence and concatenates results into a single DataFrame with a frame column. It accepts any pims-compatible image reader or a list of 2D arrays.
import trackpy as tp
import pims
frames = pims.open("particles.tif")
# Locate particles across all frames (same parameters as tp.locate)
f = tp.batch(frames, diameter=11, minmass=300, processes=1)
# processes=1 uses serial processing; set processes="auto" for multicore (requires joblib)
print(f"Total detections: {len(f)}")
print(f"Frames with data: {f['frame'].nunique()} / {len(frames)}")
print(f"Mean particles per frame: {len(f)/f['frame'].nunique():.1f}")
print(f.groupby('frame').size().describe())
# Mass histogram: use to choose minmass cutoff
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6, 4))
f['mass'].hist(bins=40, ax=ax)
ax.axvline(300, color='red', linestyle='--', label='minmass=300')
ax.set_xlabel("Integrated mass")
ax.set_ylabel("Count")
ax.set_title("Mass distribution of detections")
ax.legend()
plt.tight_layout()
plt.savefig("mass_histogram.png", dpi=150)
print("Saved mass_histogram.png — use to refine minmass cutoff")
Module 3: tp.link() — Trajectory Linking
tp.link() connects particle detections across frames into trajectories by solving a bipartite assignment problem (Hungarian algorithm). It adds a particle column (integer trajectory ID) to the positions DataFrame. search_range (pixels) is the maximum displacement between frames; memory allows a particle to disappear for up to N frames before being dropped.
import trackpy as tp
import pims
frames = pims.open("particles.tif")
f = tp.batch(frames, diameter=11, minmass=300)
# Link: search_range in pixels; memory handles brief disappearances (blinking, out-of-focus)
t = tp.link(f, search_range=5, memory=3)
print(f"Number of unique trajectories: {t['particle'].nunique()}")
print(f"Trajectory length distribution:")
print(t.groupby('particle').size().describe())
# Visualize all trajectories overlaid on the first frame
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(8, 8))
tp.plot_traj(t, superimpose=frames[0], ax=ax)
ax.set_title(f"{t['particle'].nunique()} trajectories")
plt.tight_layout()
plt.savefig("trajectories.png", dpi=150)
print("Saved trajectories.png")
Module 4: tp.filter_stubs() — Short-Track Removal
tp.filter_stubs() removes trajectories shorter than a given number of frames. Short tracks arise from noise detections, particles entering/leaving the field of view, or linking errors. Removing them improves MSD reliability because short tracks contribute high-variance MSD estimates at long lag times.
import trackpy as tp
import pims
frames = pims.open("particles.tif")
f = tp.batch(frames, diameter=11, minmass=300)
t = tp.link(f, search_range=5, memory=3)
before = t['particle'].nunique()
t_filt = tp.filter_stubs(t, threshold=10) # keep only tracks with ≥10 frames
after = t_filt['particle'].nunique()
print(f"Tracks before filtering: {before}")
print(f"Tracks after filtering (≥10 frames): {after}")
print(f"Removed {before - after} short tracks ({100*(before-after)/before:.1f}%)")
Module 5: MSD Analysis — tp.imsd() and tp.emsd()
tp.imsd() computes per-particle mean squared displacement as a function of lag time, returning a DataFrame (lag time as index, particle ID as columns). tp.emsd() computes the ensemble-averaged MSD across all particles. Both require the physical scale (mpp, microns per pixel) and frame rate (fps).
import trackpy as tp
import pims
import matplotlib.pyplot as plt
frames = pims.open("particles.tif")
f = tp.batch(frames, diameter=11, minmass=300)
t = tp.link(f, search_range=5, memory=3)
t = tp.filter_stubs(t, threshold=10)
mpp = 0.16 # microns per pixel (from microscope calibration)
fps = 10.0 # frames per second
# Individual MSD curves (one column per particle)
imsd = tp.imsd(t, mpp=mpp, fps=fps, max_lagtime=100)
print(f"IMSD shape: {imsd.shape}") # (lag times) × (particles)
# Ensemble MSD
emsd = tp.emsd(t, mpp=mpp, fps=fps, max_lagtime=100)
print(f"EMSD at lag 1 s: {emsd.iloc[0]:.4f} µm²")
# Plot ensemble MSD and fit diffusion coefficient
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import linregress
mpp = 0.16
fps = 10.0
# Fit MSD = 4*D*t (2D Brownian) over first 10 lag times
lag_s = emsd.index.values[:10] # lag times in seconds
msd_vals = emsd.values[:10]
slope, intercept, r, p, se = linregress(lag_s, msd_vals)
D = slope / 4 # diffusion coefficient in µm²/s
print(f"Diffusion coefficient D = {D:.4f} µm²/s (R²={r**2:.3f})")
fig, ax = plt.subplots(figsize=(6, 5))
ax.plot(emsd.index, emsd.values, 'o-', label='Ensemble MSD')
ax.plot(lag_s, slope * lag_s + intercept, 'r--', label=f'Fit: D={D:.4f} µm²/s')
ax.set_xlabel("Lag time (s)")
ax.set_ylabel("MSD (µm²)")
ax.set_title("Ensemble Mean Squared Displacement")
ax.legend()
plt.tight_layout()
plt.savefig("emsd.png", dpi=150)
print("Saved emsd.png")
Module 6: Motion Analysis — Characterize and Drift Correction
tp.motion.characterize() computes per-trajectory statistics (mean velocity, net displacement, straightness). tp.subtract_drift() removes bulk stage drift from trajectories before MSD analysis.
import trackpy as tp
import pims
frames = pims.open("particles.tif")
f = tp.batch(frames, diameter=11, minmass=300)
t = tp.link(f, search_range=5, memory=3)
t = tp.filter_stubs(t, threshold=10)
# Estimate and subtract drift (bulk movement of the sample/stage)
drift = tp.compute_drift(t)
print("Drift (first 5 frames):")
print(drift.head())
t_corrected = tp.subtract_drift(t.copy(), drift)
print(f"Drift subtracted from {t_corrected['particle'].nunique()} trajectories")
import trackpy as tp
# Characterize individual trajectories (requires tp.motion module)
from trackpy import motion
# Per-particle summary statistics
char = motion.characterize(t, mpp=0.16, fps=10.0)
print(char.columns.tolist())
# Columns: 'alpha' (anomalous exponent), 'D_app' (apparent diffusion), 'r^2' (fit quality)
print(char[['alpha', 'D_app']].describe())
# alpha ~ 1.0: Brownian; alpha < 1: confined/subdiffusion; alpha > 1: directed/superdiffusion
Common Workflows
Workflow 1: Full 2D Tracking Pipeline with MSD and Diffusion Coefficient
Goal: Load a fluorescence video, locate and link particles across all frames, filter short tracks, compute MSD, and extract diffusion coefficients.
import trackpy as tp
import pims
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import linregress
# ── 1. Load image sequence ──────────────────────────────────────────────────
frames = pims.open("fluorescence_video.tif") # (T, Y, X) grayscale TIF stack
print(f"Loaded {len(frames)} frames, frame shape: {frames.frame_shape}")
# ── 2. Tune detection on a single frame ───
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
90.8kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
74.4kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
Scrapling
85.7k🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev
crawl4ai
84.8kOpen-source web crawler and scraper for LLMs and AI agents: any website into clean, LLM-ready Markdown. Run it yourself, or use Crawl4AI Cloud with one key.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
