A full-stack application for Microfilaria motion analysis. The system uses skeleton-based keypoint extraction to capture body posture and deformation over time, enabling quantitative behavioral analysis without any training data.
Compare original and tracked videos with a synchronized draggable slider. See exactly how tracking overlays map to the raw footage.
Color-coded heatmap showing overall, head, mid-body, and tail motion per worm. Click any row to view per-frame displacement charts with a rolling average for trend analysis. Hover legend items to isolate individual lines.
Upload multiple videos β they queue and process sequentially. Full job history with view, download, and delete. Re-run any job with different parameters without re-uploading.
- Head/Tail Correction β Manually flip headβtail assignment for individual worms, recomputes all metrics
- Re-run with New Parameters β Adjust parameters after processing and re-run on the same file
- Cancel Processing β Cancel active jobs mid-processing with automatic file cleanup
- Info Tooltips β Hover β icons on each metric to see what it measures and how it's computed
- Rolling Average Chart β Smoothed trend line (window of 10) below the raw timeline to reveal activity patterns
- Legend Hover Highlighting β Hover a legend item to isolate that line on the chart
- CSV/ZIP Export β Download per-worm summary and per-frame timeseries data for external analysis
Coming soon β short walkthrough videos for each feature area.
| Layer | Technology |
|---|---|
| Backend | Python 3, FastAPI |
| Frontend | React, Vite, Recharts |
| CV / Scientific | OpenCV, scikit-image, SciPy, NumPy |
| Database | SQLite |
| Video | FFmpeg (H.264 transcoding) |
| Communication | Server-Sent Events (SSE) |
Build a self-contained WormTracker.app bundle (includes FFmpeg, no Python or Node needed on the target machine):
./build.shThen launch:
open dist/WormTracker.appOr run directly to see server logs:
dist/WormTracker/WormTrackerPrerequisites for building: Python venv at
~/venv/worm-trackerwith dependencies installed, Node.js 18+, andnpm.
Run backend and frontend separately with hot-reload.
- Python 3.9+ β https://www.python.org/downloads/
- Node.js v18+ β https://nodejs.org (also installs
npm) - FFmpeg β for H.264 video transcoding
- macOS:
brew install ffmpeg - Linux:
apt install ffmpeg - Windows: https://www.gyan.dev/ffmpeg/builds/ or
choco install ffmpeg
- macOS:
# 1. Clone
git clone https://github.com/vclab/worm-tracker.git
cd worm-tracker
# 2. Python environment
python -m venv ~/venv/worm-tracker
source ~/venv/worm-tracker/bin/activate # macOS/Linux
# .\venv\Scripts\activate # Windows
pip install -r requirements.txt
# 3. Frontend dependencies
cd frontend
npm install
cd ..Two terminals:
Terminal 1 β backend:
source ~/venv/worm-tracker/bin/activate
uvicorn app.main:app --reload --port 8000Terminal 2 β frontend:
cd frontend
npm run devOpen http://127.0.0.1:5173 in your browser.
- Open the app in your browser
- Adjust tracking parameters if needed (Keypoints, Area Threshold, Max Age, Persistence)
- Select one or more video files and click Add to queue
- Jobs are processed one at a time β the Job History panel shows live progress
- Click a completed job to load its results:
- Before/after comparison slider β drag to reveal original vs. tracked video
- Download All (ZIP) β tracked video, original, keypoints (
.npz), metadata (.yaml), motion stats (.json) - Export CSV β per-worm summary and per-frame timeseries data
- Head/Tail Correction β flip headβtail assignment for individual worms, then re-download
- Motion Analysis β per-worm heatmap and timeline chart (overall, head, mid-body, tail motion)
- Use Re-run with new parameters to reprocess the same file with adjusted parameters
- Use Run on another file to reset and process a new video
| Parameter | Default | Description |
|---|---|---|
| Keypoints per worm | 15 | Skeleton sample points along each worm |
| Area threshold | 50 | Minimum pixel area to consider a blob a worm |
| Max age | 35 | Frames to keep tracking a worm after it disappears |
| Persistence | 50 | Minimum frames tracked to include a worm in output |
| File | Format | Contents |
|---|---|---|
*_tracked.mp4 |
H.264 video | Annotated video with colored skeleton keypoints and worm IDs |
*_original.* |
original format | Copy of the input video |
*_metadata.yaml |
YAML | Git version, timestamp, parameters, frame count |
*_keypoints.npz |
NumPy archive | Per-worm keypoint data β see details below |
*_motion_stats.json |
JSON | Per-worm motion values (overall, head, mid-body, tail) and aggregate stats |
*_summary.csv |
CSV | One row per worm: mean motion values (overall, head, mid-body, tail) |
*_timeseries.csv |
CSV | One row per frame window: per-worm head/mid-body/tail motion over time |
import numpy as np
with np.load("*_keypoints.npz") as npz:
print(list(npz.keys())) # e.g. ['0', '1', 'partial_2', 'partial_3']
arr = npz["0"] # shape: (num_keypoints, num_frames, 2)
y, x = arr[0, 0] # [y, x] position of keypoint 0 at frame 0Array shape: (num_keypoints, num_frames, 2) β axis 0 is keypoints along the skeleton (index 0 = head, index -1 = tail), axis 1 is frames, axis 2 is [y, x] pixel coordinates.
| Key pattern | Description |
|---|---|
"0", "1", "2", β¦ |
Fully retained worms β tracked for β₯ persistence frames and never touched a frame edge |
"partial_0", "partial_2", β¦ |
Partial worms β touched a frame edge, excluded from motion analysis |
Head/tail orientation: keypoint 0 = head (wider end), keypoint -1 = tail (narrower end). Correctable via the Head/Tail Correction tool.
| Path | Description |
|---|---|
~/Documents/WormTracker/ |
Default outputs folder (user-configurable) |
~/Documents/WormTracker/{job_id}/{timestamp}_name/ |
All outputs for a job |
~/Documents/WormTracker/jobs.db |
SQLite job history |
~/Library/Application Support/WormTracker/config.json |
App config (macOS) |
All output folders and databases are created automatically. The outputs directory can be changed via β Settings in the UI.
On Windows:
%APPDATA%/WormTracker/Β· On Linux:~/.config/WormTracker/
| Problem | Solution |
|---|---|
command not found (pip, python, node) |
Ensure Python/Node are installed and on PATH. Restart terminal. |
| Video won't play in browser | Install FFmpeg (see prerequisites) |
| CORS / network errors | Make sure backend is running at http://127.0.0.1:8000 |
| Port already in use | npm run dev -- --port 5174 |
python -m app.worm_tracker input.mov output_dir --keypoints 15 --min-area 50 --max-age 35 --persistence 50- Aaveg Shangari (linkedin)
- Faisal Qureshi
VCLab, Faculty of Science, Ontario Tech University