PyStormTracker 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. pystormtracker-0.2.1/.gitattributes +1 -0
  2. pystormtracker-0.2.1/.github/workflows/python-publish.yml +65 -0
  3. pystormtracker-0.2.1/.gitignore +70 -0
  4. pystormtracker-0.2.1/.pre-commit-config.yaml +24 -0
  5. pystormtracker-0.2.1/.zenodo.json +34 -0
  6. pystormtracker-0.2.1/CITATION.cff +46 -0
  7. pystormtracker-0.2.1/LICENSE +40 -0
  8. pystormtracker-0.2.1/PKG-INFO +146 -0
  9. pystormtracker-0.2.1/README.md +111 -0
  10. pystormtracker-0.2.1/notebooks/detect_center_latlon.ipynb +149 -0
  11. pystormtracker-0.2.1/notebooks/detect_center_latlon_img_0.png +0 -0
  12. pystormtracker-0.2.1/notebooks/detect_center_latlon_img_1.png +0 -0
  13. pystormtracker-0.2.1/notebooks/plot_tracks.ipynb +117 -0
  14. pystormtracker-0.2.1/notebooks/plot_tracks_img_0.png +0 -0
  15. pystormtracker-0.2.1/pyproject.toml +95 -0
  16. pystormtracker-0.2.1/scripts/run_cesm.sh +6 -0
  17. pystormtracker-0.2.1/scripts/run_cesm_yellowstone.sh +18 -0
  18. pystormtracker-0.2.1/scripts/run_erai_msl.sh +8 -0
  19. pystormtracker-0.2.1/scripts/run_erai_vo.sh +8 -0
  20. pystormtracker-0.2.1/scripts/run_ncep.sh +6 -0
  21. pystormtracker-0.2.1/src/pystormtracker/__init__.py +4 -0
  22. pystormtracker-0.2.1/src/pystormtracker/models/__init__.py +5 -0
  23. pystormtracker-0.2.1/src/pystormtracker/models/center.py +58 -0
  24. pystormtracker-0.2.1/src/pystormtracker/models/grid.py +40 -0
  25. pystormtracker-0.2.1/src/pystormtracker/models/tracks.py +29 -0
  26. pystormtracker-0.2.1/src/pystormtracker/simple/__init__.py +4 -0
  27. pystormtracker-0.2.1/src/pystormtracker/simple/detector.py +315 -0
  28. pystormtracker-0.2.1/src/pystormtracker/simple/linker.py +104 -0
  29. pystormtracker-0.2.1/src/pystormtracker/stormtracker.py +244 -0
  30. pystormtracker-0.2.1/tests/__init__.py +1 -0
  31. pystormtracker-0.2.1/tests/test_center.py +48 -0
  32. pystormtracker-0.2.1/tests/test_integration.py +84 -0
  33. pystormtracker-0.2.1/tests/test_simple_detector.py +60 -0
  34. pystormtracker-0.2.1/tests/test_simple_linker.py +85 -0
  35. pystormtracker-0.2.1/tests/test_tracks.py +39 -0
@@ -0,0 +1 @@
1
+ data/test/*.nc filter=lfs diff=lfs merge=lfs -text export-ignore
@@ -0,0 +1,65 @@
1
+ # This workflow will upload a Python Package to PyPI when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
+
4
+ name: Upload Python Package
5
+
6
+ on:
7
+ release:
8
+ types: [published]
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ release-build:
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.x"
23
+
24
+ - name: Build release distributions
25
+ run: |
26
+ python -m pip install build
27
+ python -m build
28
+
29
+ - name: Upload distributions
30
+ uses: actions/upload-artifact@v4
31
+ with:
32
+ name: release-dists
33
+ path: dist/
34
+
35
+ pypi-publish:
36
+ runs-on: ubuntu-latest
37
+ needs:
38
+ - release-build
39
+ permissions:
40
+ # IMPORTANT: this permission is mandatory for trusted publishing
41
+ id-token: write
42
+
43
+ # Dedicated environments with protections for publishing are strongly recommended.
44
+ environment:
45
+ name: pypi
46
+ url: https://pypi.org/project/PyStormTracker/${{ steps.get_version.outputs.version }}
47
+
48
+ steps:
49
+ - name: Get version from tag
50
+ id: get_version
51
+ run: |
52
+ # Strips 'v' prefix from tag_name (e.g. v0.2.1 -> 0.2.1)
53
+ VERSION=${{ github.event.release.tag_name }}
54
+ echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
55
+
56
+ - name: Retrieve release distributions
57
+ uses: actions/download-artifact@v4
58
+ with:
59
+ name: release-dists
60
+ path: dist/
61
+
62
+ - name: Publish release distributions to PyPI
63
+ uses: pypa/gh-action-pypi-publish@release/v1
64
+ with:
65
+ packages-dir: dist/
@@ -0,0 +1,70 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+
5
+ # C extensions
6
+ *.so
7
+
8
+ # Distribution / packaging
9
+ .Python
10
+ env/
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ *.egg-info/
23
+ .installed.cfg
24
+ *.egg
25
+
26
+ # PyInstaller
27
+ # Usually these files are written by a python script from a template
28
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
29
+ *.manifest
30
+ *.spec
31
+
32
+ # Installer logs
33
+ pip-log.txt
34
+ pip-delete-this-directory.txt
35
+
36
+ # Unit test / coverage reports
37
+ htmlcov/
38
+ .tox/
39
+ .coverage
40
+ .coverage.*
41
+ .cache
42
+ nosetests.xml
43
+ coverage.xml
44
+ *,cover
45
+
46
+ # Translations
47
+ *.mo
48
+ *.pot
49
+
50
+ # Django stuff:
51
+ *.log
52
+
53
+ # Sphinx documentation
54
+ docs/_build/
55
+
56
+ # PyBuilder
57
+ target/
58
+
59
+ # IPython intermediate checkpoints
60
+ .ipynb_checkpoints
61
+
62
+ # Python Pickle files
63
+ *.pickle
64
+
65
+ # netCDF files
66
+ *.nc
67
+ !data/test/*.nc
68
+
69
+ # CSV files
70
+ *.csv
@@ -0,0 +1,24 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+ - id: debug-statements
10
+
11
+ - repo: https://github.com/astral-sh/ruff-pre-commit
12
+ rev: v0.3.4
13
+ hooks:
14
+ # Run the linter.
15
+ - id: ruff
16
+ args: [ --fix ]
17
+ # Run the formatter.
18
+ - id: ruff-format
19
+
20
+ - repo: https://github.com/pre-commit/mirrors-mypy
21
+ rev: v1.9.0
22
+ hooks:
23
+ - id: mypy
24
+ additional_dependencies: [ types-all ]
@@ -0,0 +1,34 @@
1
+ {
2
+ "title": "PyStormTracker",
3
+ "description": "A Parallel Object-Oriented Cyclone Tracker in Python",
4
+ "creators": [
5
+ {
6
+ "name": "Yau, Albert M. W.",
7
+ "orcid": "00009-0000-7825-9627"
8
+ }
9
+ ],
10
+ "keywords": [
11
+ "cyclone tracking",
12
+ "climate variability",
13
+ "dask",
14
+ "mpi"
15
+ ],
16
+ "license": "BSD-3-Clause",
17
+ "upload_type": "software",
18
+ "version": "0.2.1",
19
+ "language": "python",
20
+ "code_repository": "https://github.com/mwyau/PyStormTracker",
21
+ "development_status": "active",
22
+ "related_identifiers": [
23
+ {
24
+ "identifier": "10.1175/JCLI-D-20-0393.1",
25
+ "relation": "isSupplementTo",
26
+ "scheme": "doi"
27
+ },
28
+ {
29
+ "identifier": "10.5281/zenodo.18868625",
30
+ "relation": "isDerivedFrom",
31
+ "scheme": "doi"
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,46 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ authors:
4
+ - family-names: Yau
5
+ given-names: Albert M. W.
6
+ email: albert@mwyau.com
7
+ title: "PyStormTracker"
8
+ version: 0.2.1
9
+ doi: 10.5281/zenodo.18764813
10
+ date-released: 2026-03-04
11
+ url: "https://github.com/mwyau/PyStormTracker"
12
+ repository-code: "https://github.com/mwyau/PyStormTracker"
13
+ license: BSD-3-Clause
14
+ keywords:
15
+ - cyclone tracking
16
+ - climate variability
17
+ - dask
18
+ - mpi
19
+ preferred-citation:
20
+ type: article
21
+ authors:
22
+ - family-names: Yau
23
+ given-names: Albert M. W.
24
+ - family-names: Chang
25
+ given-names: Edmund K. M.
26
+ title: "Finding Storm Track Activity Metrics That Are Highly Correlated with Weather Impacts. Part I: Frameworks for Evaluation and Accumulated Track Activity"
27
+ journal: "Journal of Climate"
28
+ volume: 33
29
+ issue: 23
30
+ start: 10169
31
+ end: 10186
32
+ year: 2020
33
+ doi: 10.1175/JCLI-D-20-0393.1
34
+ references:
35
+ - type: poster
36
+ authors:
37
+ - family-names: Yau
38
+ given-names: Albert M. W.
39
+ - family-names: Paul
40
+ given-names: Kevin
41
+ - family-names: Dennis
42
+ given-names: John
43
+ title: "PyStormTracker: A Parallel Object-Oriented Cyclone Tracker in Python"
44
+ collection-title: "96th American Meteorological Society Annual Meeting"
45
+ year: 2016
46
+ doi: 10.5281/zenodo.18868625
@@ -0,0 +1,40 @@
1
+ Copyright (c) 2015, University Corporation for Atmospheric Research (UCAR)
2
+ Copyright (c) 2026, Albert M. W. Yau
3
+ All rights reserved.
4
+
5
+ Developed by: Application Scalability and Performance Group
6
+ University Corporation for Atmospheric Research -
7
+ National Center for Atmospheric Research
8
+ https://www.cisl.ucar.edu/
9
+
10
+ Developed by: Albert M. W. Yau
11
+ https://github.com/mwyau/PyStormTracker
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining
14
+ a copy of this software and associated documentation files (the "Software"),
15
+ to deal with the Software without restriction, including without limitation
16
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
17
+ and/or sell copies of the Software, and to permit persons to whom
18
+ the Software is furnished to do so, subject to the following conditions:
19
+
20
+ - Redistributions of source code must retain the above copyright notice,
21
+ this list of conditions and the following disclaimers.
22
+ - Redistributions in binary form must reproduce the above copyright notice,
23
+ this list of conditions and the following disclaimers in the documentation
24
+ and/or other materials provided with the distribution.
25
+ - Neither the names of the Application Scalability and Performance (ASAP)
26
+ Group, UCAR, nor the names of its contributors may be used to endorse or
27
+ promote products derived from this Software without specific prior written
28
+ permission.
29
+
30
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
34
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40
+ POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyStormTracker
3
+ Version: 0.2.1
4
+ Summary: A Parallel Object-Oriented Cyclone Tracker in Python
5
+ Project-URL: Homepage, https://github.com/mwyau/PyStormTracker
6
+ Project-URL: Repository, https://github.com/mwyau/PyStormTracker.git
7
+ Project-URL: Issues, https://github.com/mwyau/PyStormTracker/issues
8
+ Author-email: "Albert M. W. Yau" <albert@mwyau.com>
9
+ Maintainer-email: "Albert M. W. Yau" <albert@mwyau.com>
10
+ License: BSD-3-Clause
11
+ License-File: LICENSE
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: BSD License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: dask>=2024.2.0
22
+ Requires-Dist: distributed>=2024.2.0
23
+ Requires-Dist: netcdf4>=1.6.5
24
+ Requires-Dist: numpy>=1.24.0
25
+ Requires-Dist: scipy>=1.10.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: mpi4py>=3.1.5; extra == 'dev'
28
+ Requires-Dist: mypy>=1.9.0; extra == 'dev'
29
+ Requires-Dist: netcdf4>=1.6.5; extra == 'dev'
30
+ Requires-Dist: pandas>=2.2.0; extra == 'dev'
31
+ Requires-Dist: pre-commit>=3.7.0; extra == 'dev'
32
+ Requires-Dist: pytest>=8.1.1; extra == 'dev'
33
+ Requires-Dist: ruff>=0.3.4; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # PyStormTracker
37
+
38
+ [![DOI](https://zenodo.org/badge/36328800.svg)](https://doi.org/10.5281/zenodo.18764813)
39
+
40
+ PyStormTracker provides the implementation of the "Simple Tracker" algorithm used for cyclone trajectory analysis in **Yau and Chang (2020)**. It was originally developed at the **National Center for Atmospheric Research (NCAR)** as part of the **2015 Summer Internships in Parallel Computational Science (SIParCS)** program, utilizing a task-parallel strategy with temporal decomposition and a tree reduction algorithm to process large climate datasets.
41
+
42
+ ## Features
43
+
44
+ - **Modern Python 3 Support**: Fully migrated from Python 2 with comprehensive type hints.
45
+ - **Flexible Data Support**: Works with `netCDF4` and handles various coordinate naming conventions (`lat`/`lon` vs `latitude`/`longitude`).
46
+ - **Parallel Backends**:
47
+ - **Dask (Default)**: Automatically scales to all available CPU cores on local machines.
48
+ - **MPI**: Supports distributed execution via `mpi4py`.
49
+ - **Serial**: Standard sequential execution for smaller datasets or debugging.
50
+ - **Robust Detection**: Handles masked/missing data correctly and includes automated unit/integration tests.
51
+ - **User-Friendly Output**: Results are exported directly to CSV with readable datetime strings and formatted numeric values.
52
+
53
+ ## Technical Methodology
54
+
55
+ PyStormTracker treats meteorological fields as 2D images and leverages `scipy.ndimage` for robust feature detection:
56
+
57
+ - **Local Extrema Detection**: Uses `generic_filter` with a sliding window (default 5x5) to identify local minima (cyclones) or maxima (anticyclones/vorticity).
58
+ - **Intensity & Refinement**: Applies the **Laplacian operator** (`laplace`) to measure the "sharpness" of the field at each detected center point. This is used to resolve duplicates and ensure only the most physically intense point is kept when multiple adjacent pixels are flagged.
59
+ - **Spherical Continuity**: Utilizes `mode='wrap'` for all filters to correctly handle periodic boundaries across the Prime Meridian, enabling seamless tracking across the entire globe.
60
+ - **Heuristic Linking**: Implements a nearest-neighbor linking strategy to connect detected centers into trajectories across successive time steps.
61
+
62
+ ## Installation
63
+
64
+ ### Prerequisites
65
+ - Python 3.10+
66
+ - (Optional) MS-MPI or OpenMPI for MPI support.
67
+
68
+ ### From PyPI (Recommended)
69
+ You can install the latest stable version of PyStormTracker directly from PyPI:
70
+ ```bash
71
+ pip install PyStormTracker
72
+ ```
73
+
74
+ ### From Source
75
+ 1. Clone the repository:
76
+ ```bash
77
+ git clone https://github.com/mwyau/PyStormTracker.git
78
+ cd PyStormTracker
79
+ ```
80
+
81
+ 2. Install the package in editable mode:
82
+ ```bash
83
+ pip install -e .
84
+ ```
85
+
86
+ ## Usage
87
+
88
+ Once installed, you can use the `stormtracker` command directly:
89
+
90
+ ```bash
91
+ stormtracker -i data/test/slp.2012.nc -v slp -o my_tracks
92
+ ```
93
+
94
+ ### Command Line Arguments
95
+
96
+ | Argument | Short | Description |
97
+ | :--- | :--- | :--- |
98
+ | `--input` | `-i` | **Required.** Path to the input NetCDF file. |
99
+ | `--var` | `-v` | **Required.** Variable name to track (e.g., `slp`, `vo`). |
100
+ | `--output` | `-o` | **Required.** Path to the output CSV file (appends `.csv` if missing). |
101
+ | `--num` | `-n` | Number of time steps to process. |
102
+ | `--mode` | `-m` | `min` (default) for low pressure, `max` for vorticity/high pressure. |
103
+ | `--backend` | `-b` | `dask` (default), `serial`, or `mpi`. |
104
+ | `--workers` | `-w` | Number of Dask workers (defaults to CPU core count). |
105
+
106
+ ### Examples
107
+
108
+ **Run with Dask (Auto-detected cores):**
109
+ ```bash
110
+ stormtracker -i input.nc -v slp -o tracks
111
+ ```
112
+
113
+ **Run with MPI (Distributed):**
114
+ ```bash
115
+ mpiexec -n 4 stormtracker -i input.nc -v slp -o tracks -b mpi
116
+ ```
117
+
118
+ ## Project Structure
119
+
120
+ - `src/pystormtracker/models/`: Data structures (`Center`, `Grid`, `Tracks`).
121
+ - `src/pystormtracker/simple/`: Implementation of the Simple Tracker logic (`SimpleDetector`, `SimpleLinker`).
122
+ - `src/pystormtracker/stormtracker.py`: CLI orchestration and parallel backends.
123
+
124
+ ## Testing
125
+
126
+ Run the full test suite (unit and integration tests) using `pytest`:
127
+
128
+ ```bash
129
+ pytest
130
+ ```
131
+
132
+ ## Citations
133
+
134
+ If you use this software in your research, please cite the following:
135
+
136
+ - **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, https://doi.org/10.1175/JCLI-D-20-0393.1.
137
+
138
+ - **Yau, A. M. W.**, 2026: mwyau/PyStormTracker. *Zenodo*, https://doi.org/10.5281/zenodo.18764813.
139
+
140
+ ## References
141
+
142
+ - **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.
143
+
144
+ ## License
145
+
146
+ This project is licensed under the terms found in the `LICENSE` file.
@@ -0,0 +1,111 @@
1
+ # PyStormTracker
2
+
3
+ [![DOI](https://zenodo.org/badge/36328800.svg)](https://doi.org/10.5281/zenodo.18764813)
4
+
5
+ PyStormTracker provides the implementation of the "Simple Tracker" algorithm used for cyclone trajectory analysis in **Yau and Chang (2020)**. It was originally developed at the **National Center for Atmospheric Research (NCAR)** as part of the **2015 Summer Internships in Parallel Computational Science (SIParCS)** program, utilizing a task-parallel strategy with temporal decomposition and a tree reduction algorithm to process large climate datasets.
6
+
7
+ ## Features
8
+
9
+ - **Modern Python 3 Support**: Fully migrated from Python 2 with comprehensive type hints.
10
+ - **Flexible Data Support**: Works with `netCDF4` and handles various coordinate naming conventions (`lat`/`lon` vs `latitude`/`longitude`).
11
+ - **Parallel Backends**:
12
+ - **Dask (Default)**: Automatically scales to all available CPU cores on local machines.
13
+ - **MPI**: Supports distributed execution via `mpi4py`.
14
+ - **Serial**: Standard sequential execution for smaller datasets or debugging.
15
+ - **Robust Detection**: Handles masked/missing data correctly and includes automated unit/integration tests.
16
+ - **User-Friendly Output**: Results are exported directly to CSV with readable datetime strings and formatted numeric values.
17
+
18
+ ## Technical Methodology
19
+
20
+ PyStormTracker treats meteorological fields as 2D images and leverages `scipy.ndimage` for robust feature detection:
21
+
22
+ - **Local Extrema Detection**: Uses `generic_filter` with a sliding window (default 5x5) to identify local minima (cyclones) or maxima (anticyclones/vorticity).
23
+ - **Intensity & Refinement**: Applies the **Laplacian operator** (`laplace`) to measure the "sharpness" of the field at each detected center point. This is used to resolve duplicates and ensure only the most physically intense point is kept when multiple adjacent pixels are flagged.
24
+ - **Spherical Continuity**: Utilizes `mode='wrap'` for all filters to correctly handle periodic boundaries across the Prime Meridian, enabling seamless tracking across the entire globe.
25
+ - **Heuristic Linking**: Implements a nearest-neighbor linking strategy to connect detected centers into trajectories across successive time steps.
26
+
27
+ ## Installation
28
+
29
+ ### Prerequisites
30
+ - Python 3.10+
31
+ - (Optional) MS-MPI or OpenMPI for MPI support.
32
+
33
+ ### From PyPI (Recommended)
34
+ You can install the latest stable version of PyStormTracker directly from PyPI:
35
+ ```bash
36
+ pip install PyStormTracker
37
+ ```
38
+
39
+ ### From Source
40
+ 1. Clone the repository:
41
+ ```bash
42
+ git clone https://github.com/mwyau/PyStormTracker.git
43
+ cd PyStormTracker
44
+ ```
45
+
46
+ 2. Install the package in editable mode:
47
+ ```bash
48
+ pip install -e .
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ Once installed, you can use the `stormtracker` command directly:
54
+
55
+ ```bash
56
+ stormtracker -i data/test/slp.2012.nc -v slp -o my_tracks
57
+ ```
58
+
59
+ ### Command Line Arguments
60
+
61
+ | Argument | Short | Description |
62
+ | :--- | :--- | :--- |
63
+ | `--input` | `-i` | **Required.** Path to the input NetCDF file. |
64
+ | `--var` | `-v` | **Required.** Variable name to track (e.g., `slp`, `vo`). |
65
+ | `--output` | `-o` | **Required.** Path to the output CSV file (appends `.csv` if missing). |
66
+ | `--num` | `-n` | Number of time steps to process. |
67
+ | `--mode` | `-m` | `min` (default) for low pressure, `max` for vorticity/high pressure. |
68
+ | `--backend` | `-b` | `dask` (default), `serial`, or `mpi`. |
69
+ | `--workers` | `-w` | Number of Dask workers (defaults to CPU core count). |
70
+
71
+ ### Examples
72
+
73
+ **Run with Dask (Auto-detected cores):**
74
+ ```bash
75
+ stormtracker -i input.nc -v slp -o tracks
76
+ ```
77
+
78
+ **Run with MPI (Distributed):**
79
+ ```bash
80
+ mpiexec -n 4 stormtracker -i input.nc -v slp -o tracks -b mpi
81
+ ```
82
+
83
+ ## Project Structure
84
+
85
+ - `src/pystormtracker/models/`: Data structures (`Center`, `Grid`, `Tracks`).
86
+ - `src/pystormtracker/simple/`: Implementation of the Simple Tracker logic (`SimpleDetector`, `SimpleLinker`).
87
+ - `src/pystormtracker/stormtracker.py`: CLI orchestration and parallel backends.
88
+
89
+ ## Testing
90
+
91
+ Run the full test suite (unit and integration tests) using `pytest`:
92
+
93
+ ```bash
94
+ pytest
95
+ ```
96
+
97
+ ## Citations
98
+
99
+ If you use this software in your research, please cite the following:
100
+
101
+ - **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, https://doi.org/10.1175/JCLI-D-20-0393.1.
102
+
103
+ - **Yau, A. M. W.**, 2026: mwyau/PyStormTracker. *Zenodo*, https://doi.org/10.5281/zenodo.18764813.
104
+
105
+ ## References
106
+
107
+ - **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.
108
+
109
+ ## License
110
+
111
+ This project is licensed under the terms found in the `LICENSE` file.
@@ -0,0 +1,149 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {
7
+ "collapsed": false
8
+ },
9
+ "outputs": [],
10
+ "source": [
11
+ "%pylab inline\n",
12
+ "\n",
13
+ "import sys\n",
14
+ "import numpy as np\n",
15
+ "import netCDF4\n",
16
+ "from mpl_toolkits.basemap import Basemap\n",
17
+ "import matplotlib.pyplot as plt\n",
18
+ "from ipywidgets import interact\n",
19
+ "\n",
20
+ "sys.path.append('../src/')\n",
21
+ "from pystormtracker import *"
22
+ ]
23
+ },
24
+ {
25
+ "cell_type": "code",
26
+ "execution_count": null,
27
+ "metadata": {
28
+ "collapsed": false
29
+ },
30
+ "outputs": [],
31
+ "source": [
32
+ "# Plot chart 0 only\n",
33
+ "chart = 0\n",
34
+ "size = 11\n",
35
+ "\n",
36
+ "var, time, lat, lon = get_var_handle(filename=\"../data/test/slp.2012.nc\")\n",
37
+ "lons, lats = np.meshgrid(lon[:], lat[:])\n",
38
+ "\n",
39
+ "m = Basemap(projection='cyl',llcrnrlat=-90,urcrnrlat=90,\\\n",
40
+ " llcrnrlon=0,urcrnrlon=360,resolution='c')\n",
41
+ "x, y = m(lons, lats)\n",
42
+ "\n",
43
+ "data = var[chart,:,:]\n",
44
+ "centers = detect_center_latlon(data, size=size)\n",
45
+ "center_indices = centers.nonzero()\n",
46
+ "# print(np.transpose(center_indices))\n",
47
+ "\n",
48
+ "xcenter = x[center_indices]\n",
49
+ "ycenter = y[center_indices]\n",
50
+ "\n",
51
+ "fig = plt.figure(figsize=(16,10))\n",
52
+ "ax = fig.add_axes([0.1,0.1,0.9,0.9])\n",
53
+ "m.drawcoastlines()\n",
54
+ "\n",
55
+ "clevs = np.arange(950,1080.,5.)\n",
56
+ "cs = m.contourf(x, y, data/100, clevs)\n",
57
+ "cb = m.colorbar(cs)\n",
58
+ "for xi,yi in zip(xcenter, ycenter):\n",
59
+ " plt.text(xi,yi,'L',fontsize=18,fontweight='bold',\n",
60
+ " ha='center',va='center',color='k')\n",
61
+ "plt.title('All Detected Centers, size=' + str(size) + ', chart=' + str(chart))\n",
62
+ "plt.show()"
63
+ ]
64
+ },
65
+ {
66
+ "cell_type": "code",
67
+ "execution_count": null,
68
+ "metadata": {
69
+ "collapsed": false
70
+ },
71
+ "outputs": [],
72
+ "source": [
73
+ "size = 5\n",
74
+ "\n",
75
+ "var, time, lat, lon = get_var_handle(filename=\"../data/test/slp.2012.nc\")\n",
76
+ "lons, lats = np.meshgrid(lon[:], lat[:])\n",
77
+ "\n",
78
+ "m = Basemap(projection='cyl',llcrnrlat=-90,urcrnrlat=90,\\\n",
79
+ " llcrnrlon=0,urcrnrlon=360,resolution='c')\n",
80
+ "x, y = m(lons, lats)\n",
81
+ "\n",
82
+ "def pltchart(chart):\n",
83
+ " data = var[chart,:,:]\n",
84
+ " centers = detect_center_latlon(data, size=size, threshold=10.)\n",
85
+ " center_indices = centers.nonzero()\n",
86
+ " # print(np.transpose(center_indices))\n",
87
+ " \n",
88
+ " xcenter = x[center_indices]\n",
89
+ " ycenter = y[center_indices]\n",
90
+ " \n",
91
+ " fig = plt.figure(figsize=(16,10))\n",
92
+ " ax = fig.add_axes([0.1,0.1,0.9,0.9])\n",
93
+ " m.drawcoastlines()\n",
94
+ " \n",
95
+ " clevs = np.arange(975,1100.,1.)\n",
96
+ " cs = m.contourf(x, y, data/100, clevs)\n",
97
+ " cb = m.colorbar(cs)\n",
98
+ " for xi,yi in zip(xcenter, ycenter):\n",
99
+ " plt.text(xi,yi,'L',fontsize=18,fontweight='bold',\n",
100
+ " ha='center',va='center',color='k')\n",
101
+ " plt.title('All Detected Centers, size=' + str(size) + ', chart=' + str(chart))\n",
102
+ " plt.show()\n",
103
+ "\n",
104
+ "chart = (0, len(time))\n",
105
+ " \n",
106
+ "interact(pltchart, chart=chart)"
107
+ ]
108
+ },
109
+ {
110
+ "cell_type": "code",
111
+ "execution_count": null,
112
+ "metadata": {
113
+ "collapsed": true
114
+ },
115
+ "outputs": [],
116
+ "source": []
117
+ },
118
+ {
119
+ "cell_type": "code",
120
+ "execution_count": null,
121
+ "metadata": {
122
+ "collapsed": true
123
+ },
124
+ "outputs": [],
125
+ "source": []
126
+ }
127
+ ],
128
+ "metadata": {
129
+ "kernelspec": {
130
+ "display_name": "Python 3",
131
+ "language": "python",
132
+ "name": "python3"
133
+ },
134
+ "language_info": {
135
+ "codemirror_mode": {
136
+ "name": "ipython",
137
+ "version": 3
138
+ },
139
+ "file_extension": ".py",
140
+ "mimetype": "text/x-python",
141
+ "name": "python",
142
+ "nbconvert_exporter": "python",
143
+ "pygments_lexer": "ipython3",
144
+ "version": "3.12.0"
145
+ }
146
+ },
147
+ "nbformat": 4,
148
+ "nbformat_minor": 0
149
+ }