stormtrack 0.4.0__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.
- stormtrack-0.4.0/.github/dependabot.yml +28 -0
- stormtrack-0.4.0/.github/workflows/ci.yml +82 -0
- stormtrack-0.4.0/.github/workflows/release.yml +71 -0
- stormtrack-0.4.0/.github/workflows/update-dataset.yml +104 -0
- stormtrack-0.4.0/.gitignore +30 -0
- stormtrack-0.4.0/.pre-commit-config.yaml +25 -0
- stormtrack-0.4.0/.readthedocs.yaml +22 -0
- stormtrack-0.4.0/.zenodo.json +20 -0
- stormtrack-0.4.0/CITATION.cff +36 -0
- stormtrack-0.4.0/CONTRIBUTING.md +55 -0
- stormtrack-0.4.0/LICENSE +28 -0
- stormtrack-0.4.0/PKG-INFO +321 -0
- stormtrack-0.4.0/README.md +260 -0
- stormtrack-0.4.0/codecov.yml +21 -0
- stormtrack-0.4.0/data/ibtracs/manifest.json +12 -0
- stormtrack-0.4.0/data/ibtracs/observations.parquet +0 -0
- stormtrack-0.4.0/data/ibtracs/storms.parquet +0 -0
- stormtrack-0.4.0/data/manifest.json +11 -0
- stormtrack-0.4.0/data/observations.parquet +0 -0
- stormtrack-0.4.0/data/remarks.parquet +0 -0
- stormtrack-0.4.0/data/storms.parquet +0 -0
- stormtrack-0.4.0/docs/_static/all_tracks_basin.png +0 -0
- stormtrack-0.4.0/docs/_static/all_tracks_grade.png +0 -0
- stormtrack-0.4.0/docs/_static/track_tauktae.png +0 -0
- stormtrack-0.4.0/docs/api.md +54 -0
- stormtrack-0.4.0/docs/conf.py +95 -0
- stormtrack-0.4.0/docs/contributing.md +2 -0
- stormtrack-0.4.0/docs/examples/climatology.py +478 -0
- stormtrack-0.4.0/docs/examples/plotting.py +73 -0
- stormtrack-0.4.0/docs/examples/quickstart.py +94 -0
- stormtrack-0.4.0/docs/index.md +45 -0
- stormtrack-0.4.0/docs/installation.md +107 -0
- stormtrack-0.4.0/docs/references.md +39 -0
- stormtrack-0.4.0/docs/userguide/datamodel.md +48 -0
- stormtrack-0.4.0/docs/userguide/ibtracs.md +62 -0
- stormtrack-0.4.0/docs/userguide/loading.md +44 -0
- stormtrack-0.4.0/docs/userguide/quality.md +39 -0
- stormtrack-0.4.0/docs/userguide/realtime.md +80 -0
- stormtrack-0.4.0/docs/userguide/updates.md +33 -0
- stormtrack-0.4.0/docs/userguide.md +28 -0
- stormtrack-0.4.0/pyproject.toml +106 -0
- stormtrack-0.4.0/src/stormtrack/__init__.py +67 -0
- stormtrack-0.4.0/src/stormtrack/_repo.py +57 -0
- stormtrack-0.4.0/src/stormtrack/_schema.py +254 -0
- stormtrack-0.4.0/src/stormtrack/_version.py +24 -0
- stormtrack-0.4.0/src/stormtrack/analysis.py +312 -0
- stormtrack-0.4.0/src/stormtrack/atcf.py +197 -0
- stormtrack-0.4.0/src/stormtrack/cli.py +147 -0
- stormtrack-0.4.0/src/stormtrack/compare.py +187 -0
- stormtrack-0.4.0/src/stormtrack/core.py +256 -0
- stormtrack-0.4.0/src/stormtrack/dataset.py +113 -0
- stormtrack-0.4.0/src/stormtrack/fetch.py +209 -0
- stormtrack-0.4.0/src/stormtrack/ibtracs.py +413 -0
- stormtrack-0.4.0/src/stormtrack/parse.py +411 -0
- stormtrack-0.4.0/src/stormtrack/pipeline.py +123 -0
- stormtrack-0.4.0/src/stormtrack/plot.py +545 -0
- stormtrack-0.4.0/src/stormtrack/qc.py +192 -0
- stormtrack-0.4.0/src/stormtrack/realtime.py +268 -0
- stormtrack-0.4.0/src/stormtrack/store.py +127 -0
- stormtrack-0.4.0/src/stormtrack/validate.py +161 -0
- stormtrack-0.4.0/src/stormtrack/verification.py +271 -0
- stormtrack-0.4.0/tests/test_ibtracs.py +246 -0
- stormtrack-0.4.0/tests/test_load.py +109 -0
- stormtrack-0.4.0/tests/test_parse.py +574 -0
- stormtrack-0.4.0/tests/test_pipeline.py +212 -0
- stormtrack-0.4.0/tests/test_plot.py +57 -0
- stormtrack-0.4.0/tests/test_qc.py +288 -0
- stormtrack-0.4.0/tests/test_realtime.py +401 -0
- stormtrack-0.4.0/uv.lock +5837 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Python dependencies declared in pyproject.toml.
|
|
4
|
+
- package-ecosystem: "pip"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
open-pull-requests-limit: 5
|
|
9
|
+
groups:
|
|
10
|
+
# One PR for routine minor/patch bumps to keep the noise down.
|
|
11
|
+
python-minor:
|
|
12
|
+
update-types: ["minor", "patch"]
|
|
13
|
+
labels: ["dependencies"]
|
|
14
|
+
commit-message:
|
|
15
|
+
prefix: "deps"
|
|
16
|
+
|
|
17
|
+
# GitHub Actions used in the workflows (checkout, setup-python, publish, ...).
|
|
18
|
+
- package-ecosystem: "github-actions"
|
|
19
|
+
directory: "/"
|
|
20
|
+
schedule:
|
|
21
|
+
interval: "weekly"
|
|
22
|
+
open-pull-requests-limit: 5
|
|
23
|
+
groups:
|
|
24
|
+
actions:
|
|
25
|
+
patterns: ["*"]
|
|
26
|
+
labels: ["ci", "dependencies"]
|
|
27
|
+
commit-message:
|
|
28
|
+
prefix: "ci"
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ci-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint:
|
|
16
|
+
name: lint (black + ruff)
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v7
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0 # tags for hatch-vcs version
|
|
22
|
+
- uses: astral-sh/setup-uv@v7
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
- run: uv sync --locked --extra lint
|
|
26
|
+
- name: black --check
|
|
27
|
+
run: uv run black --check .
|
|
28
|
+
- name: ruff check
|
|
29
|
+
run: uv run ruff check .
|
|
30
|
+
|
|
31
|
+
test:
|
|
32
|
+
name: test (py${{ matrix.python-version }})
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
strategy:
|
|
35
|
+
fail-fast: false
|
|
36
|
+
matrix:
|
|
37
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
38
|
+
|
|
39
|
+
steps:
|
|
40
|
+
- name: Checkout
|
|
41
|
+
uses: actions/checkout@v7
|
|
42
|
+
with:
|
|
43
|
+
fetch-depth: 0 # tags for hatch-vcs version
|
|
44
|
+
|
|
45
|
+
- uses: astral-sh/setup-uv@v7
|
|
46
|
+
with:
|
|
47
|
+
enable-cache: true
|
|
48
|
+
|
|
49
|
+
- name: Sync (locked) with dev extras
|
|
50
|
+
run: uv sync --locked --extra dev --python ${{ matrix.python-version }}
|
|
51
|
+
|
|
52
|
+
- name: Run tests with coverage
|
|
53
|
+
run: uv run pytest --cov=stormtrack --cov-report=xml --cov-report=term-missing
|
|
54
|
+
|
|
55
|
+
- name: Upload coverage to Codecov
|
|
56
|
+
uses: codecov/codecov-action@v7
|
|
57
|
+
with:
|
|
58
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
59
|
+
files: ./coverage.xml
|
|
60
|
+
flags: py${{ matrix.python-version }}
|
|
61
|
+
name: py${{ matrix.python-version }}
|
|
62
|
+
fail_ci_if_error: false
|
|
63
|
+
|
|
64
|
+
docs:
|
|
65
|
+
name: build docs (validation only)
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
# Only build docs once every other check (tests + lint) is green.
|
|
68
|
+
needs: [test, lint]
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v7
|
|
71
|
+
with:
|
|
72
|
+
fetch-depth: 0 # tags for hatch-vcs version
|
|
73
|
+
- uses: astral-sh/setup-uv@v7
|
|
74
|
+
with:
|
|
75
|
+
enable-cache: true
|
|
76
|
+
- name: Sync (locked) with docs extras
|
|
77
|
+
run: uv sync --locked --extra docs
|
|
78
|
+
# Build only, to catch broken docs on a push/PR. Nothing is uploaded or
|
|
79
|
+
# published from here — the hosted docs (incl. per-PR previews) are built
|
|
80
|
+
# by Read the Docs, not GitHub.
|
|
81
|
+
- name: Build HTML docs (executes example notebooks)
|
|
82
|
+
run: uv run sphinx-build -b html -W --keep-going docs docs/_build/html
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# On a new release (a v* tag, or the update-dataset pipeline after it bumps the
|
|
4
|
+
# version), build the distributions and publish them straight to TestPyPI + PyPI.
|
|
5
|
+
# Nothing is uploaded to GitHub: no workflow artifacts, and the GitHub Release
|
|
6
|
+
# carries notes only (no dist files attached).
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
workflow_call:
|
|
12
|
+
inputs:
|
|
13
|
+
ref:
|
|
14
|
+
description: "Tag/ref to build and release"
|
|
15
|
+
required: false
|
|
16
|
+
type: string
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
release:
|
|
23
|
+
name: Build and publish
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
permissions:
|
|
26
|
+
contents: write # create the GitHub Release (notes only)
|
|
27
|
+
id-token: write # trusted publishing to PyPI/TestPyPI (OIDC)
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7
|
|
30
|
+
with:
|
|
31
|
+
ref: ${{ inputs.ref || github.ref }}
|
|
32
|
+
fetch-depth: 0
|
|
33
|
+
|
|
34
|
+
- uses: actions/setup-python@v7
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.12"
|
|
37
|
+
|
|
38
|
+
- uses: astral-sh/setup-uv@v7
|
|
39
|
+
with:
|
|
40
|
+
enable-cache: true
|
|
41
|
+
|
|
42
|
+
- name: Build distributions
|
|
43
|
+
run: |
|
|
44
|
+
uv build # sdist + wheel (version from the git tag)
|
|
45
|
+
uvx twine check dist/*
|
|
46
|
+
|
|
47
|
+
- name: Publish to TestPyPI
|
|
48
|
+
# TestPyPI is a smoke test, not the release — don't let its flakiness
|
|
49
|
+
# (it times out sometimes) block the real PyPI publish below.
|
|
50
|
+
continue-on-error: true
|
|
51
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
52
|
+
with:
|
|
53
|
+
repository-url: https://test.pypi.org/legacy/
|
|
54
|
+
skip-existing: true
|
|
55
|
+
# Both publishes share one dist/; let only the PyPI step generate the
|
|
56
|
+
# PEP 740 attestations, otherwise the second publish errors on the
|
|
57
|
+
# attestation files the first one left behind.
|
|
58
|
+
attestations: false
|
|
59
|
+
|
|
60
|
+
- name: Publish to PyPI
|
|
61
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
62
|
+
with:
|
|
63
|
+
skip-existing: true
|
|
64
|
+
|
|
65
|
+
# Marks the release in GitHub with auto-generated notes. No dist files are
|
|
66
|
+
# attached — the artifacts live on PyPI/TestPyPI.
|
|
67
|
+
- name: Create GitHub Release (notes only)
|
|
68
|
+
uses: softprops/action-gh-release@v3
|
|
69
|
+
with:
|
|
70
|
+
tag_name: ${{ inputs.ref || github.ref_name }}
|
|
71
|
+
generate_release_notes: true
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
name: Update dataset
|
|
2
|
+
|
|
3
|
+
# Rebuild the committed datasets (IMD workbook + IBTrACS North Indian Ocean) once a month.
|
|
4
|
+
# - If IMD hasn't changed, nothing is committed and no release is made.
|
|
5
|
+
# - If IMD changed and the new file parses + validates, data/ is updated,
|
|
6
|
+
# committed, the version is bumped + tagged, and a release is published.
|
|
7
|
+
# - If the new file fails to parse or validate, the job FAILS (red X + GitHub's
|
|
8
|
+
# failure notification email) and the committed dataset is left untouched.
|
|
9
|
+
on:
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: "0 6 1 * *" # 06:00 UTC on the 1st of every month
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
inputs:
|
|
14
|
+
force:
|
|
15
|
+
description: "Rebuild even if the IMD source is unchanged"
|
|
16
|
+
type: boolean
|
|
17
|
+
default: false
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write # push the refreshed data/, version bump, and tag
|
|
21
|
+
|
|
22
|
+
concurrency:
|
|
23
|
+
group: update-dataset
|
|
24
|
+
cancel-in-progress: false
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
update:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
outputs:
|
|
30
|
+
changed: ${{ steps.commit.outputs.changed }}
|
|
31
|
+
version: ${{ steps.commit.outputs.version }}
|
|
32
|
+
steps:
|
|
33
|
+
- name: Checkout
|
|
34
|
+
uses: actions/checkout@v7
|
|
35
|
+
with:
|
|
36
|
+
fetch-depth: 0 # tags needed so hatch-vcs derives the version
|
|
37
|
+
|
|
38
|
+
- name: Set up Python
|
|
39
|
+
uses: actions/setup-python@v7
|
|
40
|
+
with:
|
|
41
|
+
python-version: "3.12"
|
|
42
|
+
|
|
43
|
+
- uses: astral-sh/setup-uv@v7
|
|
44
|
+
with:
|
|
45
|
+
enable-cache: true
|
|
46
|
+
|
|
47
|
+
- name: Install package (with pipeline extra)
|
|
48
|
+
run: uv pip install --system -e ".[all]"
|
|
49
|
+
|
|
50
|
+
# If this step exits non-zero (parse/validation failure) the job fails and
|
|
51
|
+
# no commit happens — the previous dataset stays in place.
|
|
52
|
+
- name: Rebuild dataset from IMD
|
|
53
|
+
run: |
|
|
54
|
+
stormtrack build --data-dir data \
|
|
55
|
+
${{ (github.event_name == 'workflow_dispatch' && inputs.force) && '--force' || '' }}
|
|
56
|
+
|
|
57
|
+
# Independent fail-safe: a bad IBTrACS file leaves data/ibtracs untouched.
|
|
58
|
+
- name: Rebuild IBTrACS (North Indian Ocean) dataset
|
|
59
|
+
run: stormtrack build-ibtracs --data-dir data ${{ (github.event_name == 'workflow_dispatch' && inputs.force) && '--force' || '' }}
|
|
60
|
+
|
|
61
|
+
- name: Commit and tag if the dataset changed
|
|
62
|
+
id: commit
|
|
63
|
+
run: |
|
|
64
|
+
if [ -z "$(git status --porcelain data)" ]; then
|
|
65
|
+
echo "No dataset changes to commit."
|
|
66
|
+
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
67
|
+
exit 0
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
git config user.name "github-actions[bot]"
|
|
71
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
72
|
+
|
|
73
|
+
# Version comes from the git tag (hatch-vcs): bump the patch of the
|
|
74
|
+
# latest v* tag. No source file to edit.
|
|
75
|
+
LATEST="$(git describe --tags --abbrev=0 --match 'v*' 2>/dev/null || echo v0.0.0)"
|
|
76
|
+
NEW_VERSION="$(python - "$LATEST" <<'PY'
|
|
77
|
+
import re, sys
|
|
78
|
+
m = re.match(r"v(\d+)\.(\d+)\.(\d+)", sys.argv[1])
|
|
79
|
+
major, minor, patch = map(int, m.groups())
|
|
80
|
+
print(f"v{major}.{minor}.{patch + 1}")
|
|
81
|
+
PY
|
|
82
|
+
)"
|
|
83
|
+
|
|
84
|
+
git add data
|
|
85
|
+
git commit -m "data: refresh IMD best tracks and IBTrACS NI (${NEW_VERSION})"
|
|
86
|
+
git tag "${NEW_VERSION}"
|
|
87
|
+
git push origin HEAD --follow-tags
|
|
88
|
+
|
|
89
|
+
echo "Committed dataset update and tagged ${NEW_VERSION}."
|
|
90
|
+
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
91
|
+
echo "version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
|
|
92
|
+
|
|
93
|
+
# Publish only when the dataset actually changed. Reuses the release pipeline
|
|
94
|
+
# (build -> TestPyPI -> PyPI -> GitHub Release) against the freshly-created tag.
|
|
95
|
+
release:
|
|
96
|
+
needs: update
|
|
97
|
+
if: needs.update.outputs.changed == 'true'
|
|
98
|
+
uses: ./.github/workflows/release.yml
|
|
99
|
+
with:
|
|
100
|
+
ref: ${{ needs.update.outputs.version }}
|
|
101
|
+
permissions:
|
|
102
|
+
contents: write
|
|
103
|
+
id-token: write
|
|
104
|
+
secrets: inherit
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.DS_Store
|
|
2
|
+
src/stormtrack/_version.py
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.py[cod]
|
|
5
|
+
*.egg-info/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.coverage
|
|
11
|
+
coverage.xml
|
|
12
|
+
htmlcov/
|
|
13
|
+
|
|
14
|
+
# Docs build artifacts
|
|
15
|
+
docs/_build/
|
|
16
|
+
docs/jupyter_execute/
|
|
17
|
+
docs/**/jupyter_execute/
|
|
18
|
+
.jupyter_cache/
|
|
19
|
+
docs/api/_autosummary/
|
|
20
|
+
*.xlsx
|
|
21
|
+
*.parquet
|
|
22
|
+
.cache/
|
|
23
|
+
|
|
24
|
+
# ...but the *published* dataset committed by the pipeline must be tracked.
|
|
25
|
+
!data/
|
|
26
|
+
!data/*.parquet
|
|
27
|
+
!data/manifest.json
|
|
28
|
+
!data/ibtracs/
|
|
29
|
+
!data/ibtracs/*.parquet
|
|
30
|
+
!data/ibtracs/manifest.json
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Style / syntax gate. Runs on `git commit` and `git push`.
|
|
2
|
+
# Install once: pre-commit install --hook-type pre-commit --hook-type pre-push
|
|
3
|
+
default_stages: [pre-commit, pre-push]
|
|
4
|
+
|
|
5
|
+
repos:
|
|
6
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
7
|
+
rev: v4.6.0
|
|
8
|
+
hooks:
|
|
9
|
+
- id: trailing-whitespace
|
|
10
|
+
- id: end-of-file-fixer
|
|
11
|
+
- id: check-yaml
|
|
12
|
+
- id: check-toml
|
|
13
|
+
- id: check-added-large-files
|
|
14
|
+
args: ["--maxkb=2048"]
|
|
15
|
+
|
|
16
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
17
|
+
rev: v0.15.21
|
|
18
|
+
hooks:
|
|
19
|
+
- id: ruff
|
|
20
|
+
args: ["--fix"]
|
|
21
|
+
|
|
22
|
+
- repo: https://github.com/psf/black
|
|
23
|
+
rev: 26.5.1
|
|
24
|
+
hooks:
|
|
25
|
+
- id: black
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Read the Docs build configuration
|
|
2
|
+
# https://docs.readthedocs.io/en/stable/config-file/v2.html
|
|
3
|
+
version: 2
|
|
4
|
+
|
|
5
|
+
build:
|
|
6
|
+
os: ubuntu-24.04
|
|
7
|
+
tools:
|
|
8
|
+
python: "3.12"
|
|
9
|
+
|
|
10
|
+
sphinx:
|
|
11
|
+
configuration: docs/conf.py
|
|
12
|
+
fail_on_warning: false
|
|
13
|
+
|
|
14
|
+
python:
|
|
15
|
+
install:
|
|
16
|
+
- method: pip
|
|
17
|
+
path: .
|
|
18
|
+
extra_requirements:
|
|
19
|
+
- docs
|
|
20
|
+
|
|
21
|
+
formats:
|
|
22
|
+
- htmlzip
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "stormtrack: Tropical-cyclone best tracks and forecasts in Python (IMD, IBTrACS, NHC/JTWC)",
|
|
3
|
+
"description": "A Python library that serves tropical-cyclone best tracks (the India Meteorological Department RSMC New Delhi record and IBTrACS) and real-time NHC/JTWC forecasts as tidy pandas DataFrames and CF-style xarray Datasets, with analysis, comparison and forecast-verification tools. The parsed datasets are kept up to date automatically.",
|
|
4
|
+
"upload_type": "software",
|
|
5
|
+
"access_right": "open",
|
|
6
|
+
"license": "BSD-3-Clause",
|
|
7
|
+
"creators": [
|
|
8
|
+
{ "name": "Syed, Hamid Ali", "orcid": "0000-0002-7188-2544" }
|
|
9
|
+
],
|
|
10
|
+
"keywords": [
|
|
11
|
+
"cyclone",
|
|
12
|
+
"best-track",
|
|
13
|
+
"IMD",
|
|
14
|
+
"IBTrACS",
|
|
15
|
+
"North Indian Ocean",
|
|
16
|
+
"meteorology",
|
|
17
|
+
"xarray",
|
|
18
|
+
"pandas"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it using the metadata below."
|
|
3
|
+
title: "stormtrack: Tropical-cyclone best tracks and forecasts in Python (IMD, IBTrACS, NHC/JTWC)"
|
|
4
|
+
type: software
|
|
5
|
+
authors:
|
|
6
|
+
- family-names: Syed
|
|
7
|
+
given-names: Hamid Ali
|
|
8
|
+
orcid: "https://orcid.org/0000-0002-7188-2544"
|
|
9
|
+
repository-code: "https://github.com/atmospy/stormtrack"
|
|
10
|
+
url: "https://stormtrack.readthedocs.io/"
|
|
11
|
+
license: BSD-3-Clause
|
|
12
|
+
keywords:
|
|
13
|
+
- cyclone
|
|
14
|
+
- best-track
|
|
15
|
+
- IMD
|
|
16
|
+
- IBTrACS
|
|
17
|
+
- forecast verification
|
|
18
|
+
- North Indian Ocean
|
|
19
|
+
- meteorology
|
|
20
|
+
- xarray
|
|
21
|
+
- pandas
|
|
22
|
+
# Zenodo Concept DOI (represents ALL versions and always resolves to the latest,
|
|
23
|
+
# so it never changes between releases — this is the one to cite).
|
|
24
|
+
doi: 10.5281/zenodo.21301659
|
|
25
|
+
# Preferred citation: a release-agnostic reference (year only, no per-release
|
|
26
|
+
# date or version) so citations stay uniform across releases.
|
|
27
|
+
preferred-citation:
|
|
28
|
+
type: software
|
|
29
|
+
title: "stormtrack: Tropical-cyclone best tracks and forecasts in Python (IMD, IBTrACS, NHC/JTWC)"
|
|
30
|
+
authors:
|
|
31
|
+
- family-names: Syed
|
|
32
|
+
given-names: Hamid Ali
|
|
33
|
+
orcid: "https://orcid.org/0000-0002-7188-2544"
|
|
34
|
+
year: 2026
|
|
35
|
+
doi: 10.5281/zenodo.21301659
|
|
36
|
+
url: "https://stormtrack.readthedocs.io/"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Contributing to stormtrack
|
|
2
|
+
|
|
3
|
+
Thanks for helping! Bug reports, fixes, and features are all welcome via
|
|
4
|
+
[issues](https://github.com/atmospy/stormtrack/issues) and pull requests.
|
|
5
|
+
|
|
6
|
+
## Development setup ([uv](https://docs.astral.sh/uv/))
|
|
7
|
+
|
|
8
|
+
[uv](https://docs.astral.sh/uv/) is the fastest way to get a dev environment.
|
|
9
|
+
`uv sync` installs the **exact, locked** dependencies from `uv.lock` into `.venv`:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv sync --extra dev --extra plot --extra docs # everything, reproducibly
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
(Plain `pip` works too: `pip install -e ".[dev]"`.) The version is derived from
|
|
16
|
+
git tags by [hatch-vcs](https://github.com/ofek/hatch-vcs), so there's no
|
|
17
|
+
`__version__` to edit. If you change dependencies in `pyproject.toml`, refresh
|
|
18
|
+
the lock with `uv lock` and commit it.
|
|
19
|
+
|
|
20
|
+
## Checks
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv run pytest # tests (cartopy plot tests skip without cartopy)
|
|
24
|
+
uv run black . && uv run ruff check . # format + lint
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Install the pre-commit hooks so these run automatically:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uv pip install pre-commit
|
|
31
|
+
pre-commit install --hook-type pre-commit --hook-type pre-push
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Workflow
|
|
35
|
+
|
|
36
|
+
Never push to `main` directly. Create a branch, open a PR, and let CI (lint +
|
|
37
|
+
tests on Python 3.9–3.14 + docs build) go green before merging:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git switch -c my-change
|
|
41
|
+
# ... commit ...
|
|
42
|
+
git push -u origin my-change # then open a PR
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Releases
|
|
46
|
+
|
|
47
|
+
Releases are cut from a git tag — no source edit. Tag `main` and push:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git tag v0.2.6 && git push origin v0.2.6
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
That triggers the release workflow (build → TestPyPI → PyPI → GitHub Release →
|
|
54
|
+
Zenodo). The dataset in `data/` also auto-updates monthly and cuts its own
|
|
55
|
+
patch release when IMD publishes new data.
|
stormtrack-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Hamid Ali Syed
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|