A High-Performance Cyclone Tracker in Python
Project description
PyStormTracker
PyStormTracker is a high-performance Python package for cyclone trajectory analysis. It implements the "Simple Tracker" algorithm described in Yau and Chang (2020) and provides a scalable framework for processing large-scale climate datasets like ERA5.
The project is currently being expanded to include a Python port of the adaptive constraints tracking algorithm from Hodges (1999) (originally in C) and the Accumulated Track Activity metrics from Yau and Chang (2020) (originally in Matlab).
Initially developed at the National Center for Atmospheric Research (NCAR) as part of the 2015 SIParCS program, PyStormTracker leverages task-parallel strategies and tree reduction algorithms to efficiently process large-scale climate datasets.
Features
- High-Performance Architecture: Uses an Array-Backed data model to eliminate Python object overhead and ensure zero-copy serialization during parallel execution. Achieves up to 11.8x speedup in serial workloads.
- JIT-Optimized Kernels: Core mathematical filters are implemented in Numba, running at raw C speeds while releasing the GIL for true multi-process execution.
- Xarray Native: Seamlessly handles NetCDF and GRIB formats with coordinate-aware processing and robust variable alias handling (e.g.,
msl/slp,lon/longitude). - Scalable Backends:
- Serial (Default): Standard sequential execution.
- Dask: Multi-process tree-reduction for local or distributed scaling.
- MPI: High-performance distributed execution via
mpi4py.
- Typed & Modern: Built for Python 3.11+ with strict type safety and
mypycompliance. - Interoperable: Full support for the standard IMILAST intercomparison format (
.txt) with human-readable datetime strings.
Significant performance gains in v0.4.0+ compared to the legacy v0.3.3 architecture on high-resolution ERA5 data.
Technical Methodology
PyStormTracker treats meteorological fields as 2D images and leverages JIT-compiled Numba loops for high-performance feature detection:
- Local Extrema Detection: Employs an optimized sliding window filter to efficiently identify local minima (e.g., cyclones) or maxima (e.g., anticyclones, vorticity).
- Intensity & Refinement: Applies the discrete Laplacian operator to measure the "sharpness" of the field at each candidate center. This metric resolves duplicate detections, ensuring only the most physically intense point is retained when adjacent pixels are flagged.
- Trajectory Linking: Connects detected centers across consecutive time steps into continuous trajectories using a vectorized nearest-neighbor heuristic linking strategy.
Documentation
Full documentation, including API references and advanced usage examples, is available at pystormtracker.readthedocs.io.
Installation
Prerequisites
- Python 3.11+
- (Optional) OpenMPI for MPI support.
- Windows Users: the
eccodeslibGRIB helper library is only required on Linux/macOS. (Note: GRIB/ecCodes support on Windows is currently experimental and untested).
From PyPI (Recommended)
You can install the latest stable version of PyStormTracker directly from PyPI:
Using pip (standard):
pip install PyStormTracker
Using uv (recommended):
# For use as a CLI tool
uv tool install PyStormTracker
# For use as a library in your project
uv add PyStormTracker
From Source
Install with uv (Recommended):
git clone https://github.com/mwyau/PyStormTracker.git
cd PyStormTracker
uv sync
Usage
Command Line Interface
Once installed, you can use the stormtracker command directly:
stormtracker -i data.nc -v msl -o my_tracks
Command Line Arguments
| Argument | Short | Description |
|---|---|---|
--input |
-i |
Required. Path to the input NetCDF/GRIB file. |
--var |
-v |
Required. Variable name to track (e.g., msl, vo). |
--output |
-o |
Required. Path to the output track file (appends .txt if missing). |
--num |
-n |
Number of time steps to process. |
--threshold |
-t |
Detection threshold (defaults: 1e-4 for vo, 0.0 otherwise). |
--mode |
-m |
min (default) for low pressure, max for vorticity/high pressure. |
--backend |
-b |
serial (default), dask, or mpi. |
--workers |
-w |
Number of Dask workers (defaults to CPU core count). |
--engine |
-e |
Xarray engine (e.g., h5netcdf, netcdf4, cfgrib). |
Python API
You can easily integrate PyStormTracker into your own scripts or Jupyter Notebooks:
import pystormtracker as pst
# 1. Instantiate the tracker (defaults to Serial backend)
tracker = pst.SimpleTracker()
# 2. Run the tracking algorithm. Returns an array-backed Tracks object.
tracks = tracker.track(
infile="data.nc",
varname="msl",
mode="min",
start_time="2025-01-01", # Optional: limit by start date
end_time="2025-01-31", # Optional: limit by end date
backend="dask", # Optional: use 'serial', 'dask', or 'mpi'
n_workers=4
)
# 3. Analyze the results programmatically
for track in tracks:
if len(track) >= 8:
print(f"Track {track.track_id} lived for {len(track)} steps.")
# 4. Export results
tracks.write("output.txt", format="imilast")
Sample Data
Sample datasets for testing and benchmarking are hosted in the PyStormTracker-Data repository.
Development
Setup
Using uv is the recommended way to set up your environment:
# Install dependencies and sync virtual environment
uv sync
Quality Control
Run automated checks using uv run:
Linting & Formatting:
uv run ruff check . --fix
uv run ruff format .
Type Checking:
uv run mypy src/
Tiered Testing
To keep development cycles fast, testing is tiered:
- Fast Tests: Default local runs (skips integration tests).
- Integration Tests: Integration and regression tests.
- Local: Runs "short" variants (60 time steps) to ensure backend consistency quickly.
- CI: Runs "full" (all time steps) variants, including legacy regressions.
- Full Suite: Everything.
Run fast unit tests only (Default):
uv run pytest
Run integration tests (Short variants locally):
uv run pytest --run-integration
Run everything:
uv run pytest --run-all
Citations
If you use this software in your research, please cite the following:
-
Yau, A. M. W., 2026: mwyau/PyStormTracker. Zenodo, https://doi.org/10.5281/zenodo.18764813.
-
Yau, A. M. W. and Chang, E. K. M., 2020: Finding Storm Track Activity Metrics That Are Highly Correlated with Weather Impacts. J. Climate, 33, 10169–10186, https://doi.org/10.1175/JCLI-D-20-0393.1.
References
-
Yau, A. M. W., K. Paul and J. Dennis, 2016: PyStormTracker: A Parallel Object-Oriented Cyclone Tracker in Python. 96th American Meteorological Society Annual Meeting, New Orleans, LA. Zenodo, https://doi.org/10.5281/zenodo.18868625.
-
Neu, U., et al., 2013: IMILAST: A Community Effort to Intercompare Extratropical Cyclone Detection and Tracking Algorithms. Bull. Amer. Meteor. Soc., 94, 529–547, https://doi.org/10.1175/BAMS-D-11-00154.1.
- IMILAST Intercomparison Protocol: https://proclim.scnat.ch/en/activities/project_imilast/intercomparison
- IMILAST Data Download: https://proclim.scnat.ch/en/activities/project_imilast/data_download
-
Hodges, K. I., 1999: Adaptive Constraints for Feature Tracking. Mon. Wea. Rev., 127, 1362–1373, https://doi.org/10.1175/1520-0493(1999)127<1362:ACFFT>2.0.CO;2.
License
This project is licensed under the BSD-3-Clause terms found in the LICENSE file.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pystormtracker-0.4.1.tar.gz.
File metadata
- Download URL: pystormtracker-0.4.1.tar.gz
- Upload date:
- Size: 930.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71e842a963b589f7e2939094e44765cbd96d34bba4feeea1dd42dbffa6f840a5
|
|
| MD5 |
38711292c4edee5a5d81df4a2ed7a9c0
|
|
| BLAKE2b-256 |
884fec08ca0be1923c4c469201a3acc5e8f81a3dd84881ffc3ac601ac4893d48
|
Provenance
The following attestation bundles were made for pystormtracker-0.4.1.tar.gz:
Publisher:
python-publish.yml on mwyau/PyStormTracker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pystormtracker-0.4.1.tar.gz -
Subject digest:
71e842a963b589f7e2939094e44765cbd96d34bba4feeea1dd42dbffa6f840a5 - Sigstore transparency entry: 1127620153
- Sigstore integration time:
-
Permalink:
mwyau/PyStormTracker@67c59024aa18021937be4850a2321c8186c89afe -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mwyau
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@67c59024aa18021937be4850a2321c8186c89afe -
Trigger Event:
workflow_run
-
Statement type:
File details
Details for the file pystormtracker-0.4.1-py3-none-any.whl.
File metadata
- Download URL: pystormtracker-0.4.1-py3-none-any.whl
- Upload date:
- Size: 29.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c250219d330e4f84515c6528cbac26066218e29bd54bcadaeb44a3fd8895562c
|
|
| MD5 |
e32666e390232d717141b54a51c19d92
|
|
| BLAKE2b-256 |
eb8bd2272e7c84737010cf40b6cdb14ee365a0ca85efb6739a58c314dae3d2fa
|
Provenance
The following attestation bundles were made for pystormtracker-0.4.1-py3-none-any.whl:
Publisher:
python-publish.yml on mwyau/PyStormTracker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pystormtracker-0.4.1-py3-none-any.whl -
Subject digest:
c250219d330e4f84515c6528cbac26066218e29bd54bcadaeb44a3fd8895562c - Sigstore transparency entry: 1127620201
- Sigstore integration time:
-
Permalink:
mwyau/PyStormTracker@67c59024aa18021937be4850a2321c8186c89afe -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mwyau
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@67c59024aa18021937be4850a2321c8186c89afe -
Trigger Event:
workflow_run
-
Statement type: