PyStormTracker

CI Documentation Status codecov PyPI version TestPyPI Version Conda Version GitHub License Docker GHCR DOI


Storm Track Explorer
Interactive visualization of cyclone trajectories.

PyStormTracker is a Python package for cyclone trajectory analysis. It provides cyclone detection, trajectory construction, and track-based analysis for meteorological and climate datasets. The package includes a Numba implementation of the Simple Tracker described by Yau and Chang (2020) and TRACK algorithms described by Hodges (1994, 1995, 1999). The project was initially developed at the National Center for Atmospheric Research (NCAR) during the 2015 SIParCS program.

Features

  • Vectorized, array-backed data model: Stores track coordinates, times, identifiers, and variables in contiguous NumPy arrays. Track objects are views over this storage rather than independent collections of center objects.

  • Numba JIT-compiled kernels: Detection, Laplacian intensity, great-circle geometry, connected-component labeling (CCL), subgrid refinement, and Modified Greedy Exchange (MGE) kernels use cached, GIL-free Numba functions.

  • Multiple Algorithms:

    • Simple: Fast, local-extrema detection and deterministic nearest-neighbor linking.

    • Hodges (TRACK): Thresholded object detection with connected-component labeling (CCL), spherical cost functions, adaptive constraints, and iterative Modified Greedy Exchange (MGE) linking based on TRACK. See the Hodges implementation documentation and spectral filtering accuracy.

    • HEALPix: Thresholded object detection on a one-dimensional HEALPix neighbor graph, followed by the Hodges MGE linker.

  • Coordinate-aware Xarray input: DataLoader opens NetCDF, GRIB, and Zarr data, resolves common variable and coordinate aliases, and identifies regular latitude-longitude, full Gaussian, reduced-Gaussian, projected, and HEALPix grids.

  • Execution Backends:

    • Simple: Serial, threaded Dask detection, and MPI detection. Parallel paths gather detections before one linking pass.

    • Hodges and HEALPix: Serial only; unsupported backend selections raise an error.

  • Typed Implementation: Built for Python 3.11+ with strict type safety and mypy compliance.

  • Formats and analysis: Reads IMILAST and JSON track data; writes IMILAST, TRACK tdump, and JSON. Analysis functions include secondary-variable sampling, track matching, gridded cyclone and track metrics, Eulerian variance and wind indices, CORMAX, and CCA/PCA truncation cross-validation.

v0.4.0 benchmark timing breakdown

Measured v0.3.3 and v0.4.0 timings for the 0.25° ERA5 benchmark described in the benchmark documentation.

Technical Methodology

The trackers apply the following stages:

  • Preprocessing: Optional spherical harmonic transform (SHT) filtering on global grids, discrete cosine transform (DCT) filtering on regional grids, Sardeshmukh-Hoskins spectral tapering, and regridding to polar stereographic or HEALPix coordinates. Full and reduced Gaussian grids are handled through ducc0 geometry metadata.

  • Detection: The Simple tracker applies a sliding-window local-extrema filter and uses the discrete Laplacian magnitude to select among adjacent extrema. Hodges and HEALPix use thresholding, connected-component labeling, object filtering, and local-extrema detection.

  • Subgrid Refinement: Optional local quadratic surface fitting estimates a stationary point below the grid spacing. It is off by default for Simple and on by default for Hodges and HEALPix. On periodic global Hodges grids, a RectSphereBivariateSpline value is also evaluated at the quadratic center.

  • Linking: Simple uses deterministic nearest-neighbor linking with a vectorized great-circle distance matrix. Hodges and HEALPix use Modified Greedy Exchange with spherical displacement and smoothness constraints.

Documentation

Full documentation, including API references and advanced usage examples, is available at pystormtracker.readthedocs.io.

Installation

Prerequisites

  • Python 3.11+

  • Message Passing Interface (MPI):

    • Linux/macOS: OpenMPI is recommended and included as a development dependency.

    • Windows: Use winget install -e --id Microsoft.msmpi (recommended) or MS-MPI.

  • Spherical Harmonic Transform (SHT) engine:

    • ducc0 provides scalar and spin-weighted spherical harmonic transforms, reduced-grid synthesis, and HEALPix geometry.

  • Free-threaded Python:

    • Python 3.14 free-threaded support is experimental. grib and zarr modules are not supported by Python 3.14t runtime.

From PyPI

You can install the latest stable version of PyStormTracker directly from PyPI:

Using pip:

# Standard installation
pip install PyStormTracker

# With optional components
pip install "PyStormTracker[mpi]"     # Includes mpi4py for distributed execution
pip install "PyStormTracker[grib]"    # Includes GRIB support
pip install "PyStormTracker[netcdf4]" # Includes NetCDF4 backend
pip install "PyStormTracker[zarr]"    # Includes Zarr support (with remote HTTP/S3/GS)
pip install "PyStormTracker[eof]"     # Includes xeofs for CCA/PCA analysis
pip install "PyStormTracker[all]"     # Includes non-visualization optional components

Using uv:

# For use as a CLI tool
uv tool install "PyStormTracker[mpi]"

# For use as a library in your project
uv add "PyStormTracker[mpi]"

From Conda-Forge

You can also install PyStormTracker from conda-forge:

Using mamba:

mamba install -c conda-forge pystormtracker

Using conda:

conda install -c conda-forge pystormtracker

From Source

Install with uv:

git clone https://github.com/mwyau/PyStormTracker.git
cd PyStormTracker
uv sync

Usage

Command Line Interface

Once installed, the stormtracker command provides separate subcommands for tracking, sampling, comparison, and conversion:

1. Track Features

Run the core storm tracking algorithm (e.g., tracking cyclones in MSLP):

stormtracker track -i data.nc -v msl -o tracks.json -m min -a hodges -f json

2. Sample Variables

Extract external variables (e.g., precipitation) along existing tracks:

# Calculate mean precipitation within a 500km radius of storm centers
stormtracker sample -i tracks.json -d precip.nc -v pr -o tracks_enriched.json --method mean --radius 500

3. Match and Intercompare

Compare tracks from different datasets or ensemble members:

# Match tracks from two sources with a 200km mean distance threshold
stormtracker compare --ref era5.json --comp gfs.json --max-dist 200 --json

4. Convert & Visualize

Convert between formats or generate interactive HTML explorers:

# Generate a standalone interactive map
stormtracker convert -i tracks.json -o explorer.html -f json -F html

CLI Argument Reference

Use stormtracker <command> --help for detailed argument lists. Key options for the track command include:

Argument

Short

Description

--input

-i

Path to the input NetCDF/GRIB file.

--var

-v

Variable name to track (e.g., msl, vo).

--output

-o

Path to the output track file.

--algorithm

-a

simple (default) or hodges.

--format

-f

Output format: imilast, hodges, or json.

--mode

-m

min (default) for cyclones, max for vorticity.

--backend

-b

serial, dask, or mpi. Dask and MPI tracking currently apply only to Simple.

--workers

-w

Number of parallel workers.

--filter-range

Inclusive spectral wave-number range. Supplying it enables filtering; the default range when filtering is enabled is 5-42.

--filter, --no-filter

Override algorithm-specific filtering defaults.

--subgrid-refine, --no-subgrid-refine

Override refinement defaults. Off for simple; on for Hodges and HEALPix.

Python API

The trackers can also be called directly:

import pystormtracker as pst

tracker = pst.HodgesTracker()

tracks = tracker.track(infile="data.nc", varname="vo", mode="max")

Analyze the results programmatically

for track in tracks:
    if len(track) >= 8:
        print(f"Track {track.track_id} lived for {len(track)} steps.")

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 to set up your development environment:

# Install dependencies and sync virtual environment
uv sync --all-extras

Quality Control

Run automated checks using uv run:

Linting & Formatting:

uv run ruff check . --fix
uv run ruff format .

Type Checking:

uv run mypy .

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, doi:10.5281/zenodo.18764813.

  • Yau, A. M. W., and E. K. M. Chang, 2020: Finding Storm Track Activity Metrics That Are Highly Correlated with Weather Impacts. Part I: Frameworks for Evaluation and Accumulated Track Activity. J. Climate, 33, 10169–10186, doi:10.1175/JCLI-D-20-0393.1.

References

License

This project is licensed under the BSD-3-Clause terms found in the LICENSE file.