A standalone microbubble ULM (ultrasound localization microscopy) pipeline: beamforming, SVD clutter filtering, 3D bubble detection and localization, Kalman track linking, and interactive browser viewers — packaged as a self-contained Python package with no external acquisition stack.
Built by Aleph Neuro.
The pipeline has three stages, each exposed as a CLI subcommand:
- Beamform a neutral demodulated-IQ ultratrace into a beamformed H5
(
acquisitions/<id>/meta/compound_imageplus a saved imaging grid), using the optionalmachGPU kernel. No vendor raw-frame decoding. - Track — temporal SVD clutter filtering → 3D detection and sub-voxel localization → Kalman + Hungarian track linking → smoothing.
- View — export compact binary tracks for the animated 3D track viewer, or render a rotatable 3D SVD volume viewer.
The run subcommand chains all three (plus the data download) into one command.
This project uses uv. From the repo root:
uv sync # core: download + tracking + viewers (creates .venv)
uv sync --extra mach # + GPU MACH beamforming (CUDA host only)uv sync installs the exact, locked versions (uv.lock). Run any command with
uv run ultratrace-ulm ..., or activate the environment with
source .venv/bin/activate and call ultratrace-ulm directly.
The core install has no GPU dependency. Beamforming (beamform, and the
beamform step of run) needs the mach extra and a CUDA host.
One command — download the sample data, beamform it, track, and build the 3D track viewer:
uv run ultratrace-ulm run --spatial-tgc --frame-rate 222
cd outputs/viewer && python3 -m http.server 8080 # open http://localhost:8080Already have a beamformed file? Skip download and beamforming:
ultratrace-ulm run --beamformed beamformed.h5 --frame-rate 222
rundownloads ~98 GB and beamforms on a CUDA GPU. To avoid both, pass--beamformed. For full control over any stage, use the dedicated subcommands below instead.
Run ultratrace-ulm <command> --help for the complete flag list of any command.
| Command | Purpose |
|---|---|
download |
Fetch the public sample ultratrace (resumable). |
run |
End-to-end demo: download → beamform → track → track viewer. |
beamform |
MACH beamform a raw neutral ultratrace into a beamformed H5. |
track |
Streaming ULM tracking → smoothed tracks (+ optional bins). |
track-export |
track plus binary .bin export in one step. |
export |
Smooth and export .bin files from an existing track pickle. |
track-viewer |
Build the animated 3D track-flow viewer bundle. |
volume |
Build the rotatable 3D SVD volume viewer bundle. |
launcher |
Write a landing page linking several viewer bundles. |
doctor |
Check that the standalone runtime imports cleanly. |
Resumable download (pure stdlib, no curl needed). A sanitized neutral
ultratrace — demodulated IQ plus transmit delays and a beamforming-only config,
no raw frames or device metadata — hosted on Cloudflare R2 (~98 GB, 223
acquisitions):
ultratrace-ulm download --output sample_ultratrace.h5An interrupted download resumes in place when re-run. Use --force to restart,
--url to point at a different source.
ultratrace-ulm run \
--work-dir outputs \
--frame-rate 222 \
--svd-method adaptive \
--spatial-tgc \
--min-length 35Writes everything under --work-dir (default outputs/): the downloaded
sample, beamformed.h5, tracks.pkl / tracks_smoothed.pkl, tracks_min*.bin,
and the viewer/ bundle. Stages whose outputs already exist are skipped unless
--force is given.
--input RAW.h5— beamform this raw file instead of downloading the sample.--beamformed B.h5— start from an existing beamformed file (skip download and beamforming).--frame-rateis required by adaptive SVD; the sample runs at 222 Hz.
ultratrace-ulm beamform \
--input sample_ultratrace.h5 \
--output beamformed.h5 \
--spatial-tgcBeamform a slice with --acq-start / --num-acqs / --acq-step, or the whole
file with --all-acqs. Requires the [mach] extra and a CUDA GPU.
ultratrace-ulm track \
--beamformed beamformed.h5 \
--tracks outputs/tracks.pkl \
--svd-method adaptive --frame-rate 222 \
--sigma-threshold 2.0 --subpixel centroid \
--tracking kalman --min-track-length 5Writes outputs/tracks.pkl and a smoothed outputs/tracks_smoothed.pkl. Add
--export-dir/--min-lengths (or use track-export) to also emit .bin files.
For non-stationary microbubble tracks, prefer adaptive SVD with
--temporal-sigma 0:
ultratrace-ulm track \
--beamformed beamformed.h5 --tracks outputs/tracks.pkl \
--svd-method adaptive --frame-rate 222 --knee-filter \
--temporal-sigma 0 --sigma-threshold 2.0 --svd-low-cutoff 0.1 \
--min-distance 2 --smoothing-sigma 1.0 --tracking kalman \
--max-gap 3 --min-track-length 5 --max-cost 10A large --temporal-sigma (e.g. 7) with the fast SVD variant tends to track
stationary tissue/clutter: many more tracks that barely move. Adaptive SVD with
no temporal blur matches the production reference (~260 tracks/acquisition,
genuinely flowing).
Re-smooth and re-export .bin files from an existing pickle without re-tracking:
ultratrace-ulm export \
--tracks outputs/tracks.pkl \
--export-dir outputs \
--min-lengths 5 20 50Build the animated 3D track-flow viewer (Three.js point-flow):
ultratrace-ulm track-viewer \
--tracks outputs/tracks_smoothed.pkl \
--output-dir outputs/viewer \
--min-length 35 --beamformed beamformed.h5
cd outputs/viewer && python3 -m http.server 8080--beamformed is optional and only used to sample per-point B-mode intensity.
Build the rotatable 3D SVD volume viewer with track overlay:
ultratrace-ulm volume \
--beamformed beamformed.h5 \
--tracks outputs/tracks_smoothed.pkl \
--output-dir outputs/volume
cd outputs/volume && python3 -m http.server 8080Serve several viewer bundles behind one landing page. Export the track-viewer
and volume bundles into a shared directory, then:
ultratrace-ulm launcher \
--output-dir outputs \
--title "Ultratrace ULM" \
--subtitle "adaptive SVD" \
--viewer "viewer/|3D Track-Flow Viewer|Animated point-flow of tracks.|✨" \
--viewer "volume/|3D SVD Volume Viewer|Rotatable super-resolution volume.|🧊"This writes index.html + viewers.json. Each --viewer is
HREF|TITLE|DESCRIPTION|EMOJI (only the href is required) and may be repeated.
Every viewer bundle is static — serve its directory with any file server:
cd outputs/viewer && python3 -m http.server 8080 # http://localhost:8080MIT — © 2026 Aleph Neuro.