Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ccb7c4f
Add pressure_dimension_str arg to geopotential_thickness (#297)
aaTman Jan 11, 2026
d5ca07c
`DurationMeanError` memory fix and add time resolution option (#296)
aaTman Jan 13, 2026
f2d8cd2
Move parallel config check outside of function (#301)
aaTman Jan 13, 2026
d09f456
feat: Forecast wrapper for custom xarray datasets (#302)
darothen Jan 13, 2026
1035230
Simplify IBTrACS polars subset (#303)
aaTman Jan 14, 2026
4027de8
Update `geopotential_thickness` var names and docstring (#306)
aaTman Jan 14, 2026
1afff35
Clarify default preprocess function names; geopotential division fix …
aaTman Jan 14, 2026
5d239b8
Remove "cases" key requirement in yamls and dicts (#308)
aaTman Jan 15, 2026
4793532
remove out-of-date notebook from docs
aaTman Jan 15, 2026
ed3b9e6
CIRA Icechunk store (#310)
aaTman Jan 15, 2026
342668a
update pyproject and uv lock
aaTman Jan 16, 2026
fcd329e
Merge pull request #311 from brightbandtech:chore/upgrade-scores
aaTman Jan 16, 2026
89a9bdb
add TODO
aaTman Jan 17, 2026
94eeb98
update PR template
aaTman Jan 19, 2026
0fabca5
Remove `IndividualCaseCollection` (#317)
aaTman Jan 22, 2026
63f8b13
Cleanup docstrings in repo (#318)
aaTman Jan 24, 2026
5350563
add explanation for dim reqs (#320)
aaTman Jan 24, 2026
71f3a0b
Update `defaults` and `inputs` to include new CIRA icechunk store (#319)
aaTman Jan 24, 2026
79f4b74
Bump version from 0.2.0 to 0.3.0 (#324)
aaTman Jan 26, 2026
b1fc1b6
Updated API (#321)
aaTman Jan 26, 2026
34a3965
Golden tests (#323)
aaTman Jan 26, 2026
8979bed
PyPI Preparation (#315)
aaTman Jan 26, 2026
54f5c35
update pyproject version for release
aaTman Jan 26, 2026
c367043
Merge branch 'main' into develop
aaTman Jan 26, 2026
43fafbf
Remove duplicate function and fixtures (#326)
aaTman Jan 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Upload Python Package

on:
release:
types: [published]

permissions:
contents: read

jobs:
release-build:
name: Build release distribution
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Build release distributions
run: |
python -m pip install build
python -m build

- name: Upload distributions
uses: actions/upload-artifact@v4
with:
name: release-dists
path: dist/

pypi-publish:
name: Publish release distribution to PyPI
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
needs:
- release-build
permissions:
# IMPORTANT: this permission is mandatory for trusted publishing
id-token: write

# Dedicated environments with protections for publishing are strongly recommended.
# For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
environment:
name: ewb-pypi-release
url: https://pypi.org/p/extremeweatherbench

steps:
- name: Retrieve release distributions
uses: actions/download-artifact@v4
with:
name: release-dists
path: dist/

- name: Publish release distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/

publish-to-testpypi:
name: Publish release distribution to TestPyPI
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
needs:
- release-build

permissions:
id-token: write

environment:
name: ewb-testpypi-release
url: https://test.pypi.org/p/extremeweatherbench

steps:
- name: Retrieve release distributions
uses: actions/download-artifact@v4
with:
name: release-dists
path: dist/

- name: Publish release distributions to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
packages-dir: dist/
36 changes: 36 additions & 0 deletions .github/workflows/run-pre-commit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Run pre-commit

on:
pull_request:
branches: [main, develop]
push:
branches: [main]

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4

- name: Set up Python env with uv
uses: astral-sh/setup-uv@v4
with:
version: "0.5.6"
enable-cache: true

- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install the project
run: uv sync --all-extras --all-groups

- name: Run pre-commit hooks
run: uv run pre-commit run --all-files
32 changes: 9 additions & 23 deletions .github/workflows/ci.yaml → .github/workflows/run-tests.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
name: ci
name: Run tests

on:
pull_request:
branches: [main, develop]
push:
branches: [main]

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: pre-commit/action@v3.0.1
permissions:
contents: read

test:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.12"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4

Expand All @@ -30,24 +27,13 @@ jobs:
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
python-version: ${{ matrix.python-version }}

- name: Install the project
run: uv sync --all-extras --dev
run: uv sync --all-extras --all-groups

- name: Run tests
run: uv run pytest

- name: Generate Coverage Report
run: uv run coverage report -m

golden-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: extractions/setup-just@v3
with:
just-version: 1.43.1

- name: Run golden tests with just
run: just golden-tests
56 changes: 53 additions & 3 deletions Justfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,57 @@
# NOTE: We automatically load a .env file containing the "GH_TOKEN" environment variable
# for use with semantic-release. If this isn't present, then those commands will likely fail.
set dotenv-load

# List all available recipes
default:
@just --list

# Placeholder for golden tests
golden-tests:
@just --list
# Run the complete test suite
test:
@echo "Running tests"
uv run pytest

# Serve a local build of the project documentation at http://localhost:8000
serve-docs:
@echo "Serving docs at http://localhost:8000"
uv run --extra docs mkdocs serve

# Build the project documentation
build-docs:
@echo "Building docs"
uv run --extra docs mkdocs build

# Run the pre-commit hooks on all files in the repo
pre-commit:
@echo "Running pre-commit hooks"
uv run pre-commit run --all-files

# Run the coverage report
coverage:
@echo "Running coverage report"
uv run coverage run -m pytest
uv run coverage report

# Determine the next version number
next-version:
@echo "Determining next version"
uv run semantic-release version --print

# Create a minor release
minor-release:
@echo "Creating minor release"
uv run semantic-release -vvv --noop version --minor --no-changelog

# Create a patch release
patch-release:
@echo "Creating patch release"
uv run semantic-release -vvv --noop version --patch --no-changelog

# Upload a release to PyPI
pypi-upload tag:
@echo "Uploading release {{tag}} to PyPI"
git checkout {{tag}}
rm -rf dist
uv run python -m build
uv run twine upload dist/*
git checkout -
6 changes: 5 additions & 1 deletion data_prep/ar_bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
from dask.distributed import Client
from matplotlib.patches import Rectangle

from extremeweatherbench import cases, derived, inputs, regions, utils
import extremeweatherbench.cases as cases
import extremeweatherbench.derived as derived
import extremeweatherbench.inputs as inputs
import extremeweatherbench.regions as regions
import extremeweatherbench.utils as utils
from extremeweatherbench.events import atmospheric_river as ar

logging.basicConfig()
Expand Down
26 changes: 15 additions & 11 deletions data_prep/ibtracs_bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
import re
from importlib import resources
from typing import TYPE_CHECKING

import cartopy.crs as ccrs
import cartopy.feature as cfeature
Expand All @@ -14,8 +15,11 @@
import yaml
from matplotlib.patches import Rectangle

import extremeweatherbench as ewb
import extremeweatherbench.data
from extremeweatherbench import cases, inputs, regions, utils

if TYPE_CHECKING:
from extremeweatherbench.regions import Region

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -67,7 +71,7 @@ def calculate_extent_bounds(
bottom_lat: float,
top_lat: float,
extent_buffer: float = 250,
) -> regions.Region:
) -> Region:
"""Calculate extent bounds with buffer.

Args:
Expand All @@ -94,9 +98,9 @@ def calculate_extent_bounds(
calculate_end_point(bottom_lat, right_lon, 90, extent_buffer), 1
)

new_left_lon = np.round(utils.convert_longitude_to_360(new_left_lon), 1)
new_right_lon = np.round(utils.convert_longitude_to_360(new_right_lon), 1)
new_box = regions.BoundingBoxRegion(
new_left_lon = np.round(ewb.utils.convert_longitude_to_360(new_left_lon), 1)
new_right_lon = np.round(ewb.utils.convert_longitude_to_360(new_right_lon), 1)
new_box = ewb.regions.BoundingBoxRegion(
new_bottom_lat, new_top_lat, new_left_lon, new_right_lon
)
return new_box
Expand Down Expand Up @@ -164,10 +168,10 @@ def load_and_process_ibtracs_data():
"""
logger.info("Loading IBTrACS data...")

IBTRACS = inputs.IBTrACS(
source=inputs.IBTRACS_URI,
IBTRACS = ewb.inputs.IBTrACS(
source=ewb.inputs.IBTRACS_URI,
variables=["vmax", "slp"],
variable_mapping=inputs.IBTrACS_metadata_variable_mapping,
variable_mapping=ewb.inputs.IBTrACS_metadata_variable_mapping,
storage_options={},
)

Expand All @@ -177,7 +181,7 @@ def load_and_process_ibtracs_data():
# Get all storms from 2020 - 2025 seasons
all_storms_2020_2025_lf = IBTRACS_lf.filter(
(pl.col("SEASON").cast(pl.Int32) >= 2020)
).select(inputs.IBTrACS_metadata_variable_mapping.values())
).select(ewb.inputs.IBTrACS_metadata_variable_mapping.values())

schema = all_storms_2020_2025_lf.collect_schema()
# Convert pressure and surface wind columns to float, replacing " " with null
Expand Down Expand Up @@ -464,7 +468,7 @@ def find_storm_bounds_for_case(storm_name, storm_bounds, all_storms_df):
# If we found both, merge them by taking the bounding box that
# encompasses both
if bounds1 is not None and bounds2 is not None:
merged_bbox = regions.BoundingBoxRegion(
merged_bbox = ewb.regions.BoundingBoxRegion(
latitude_min=min(
bounds1.iloc[0].latitude_min, bounds2.iloc[0].latitude_min
),
Expand Down Expand Up @@ -537,7 +541,7 @@ def update_cases_with_storm_bounds(storm_bounds, all_storms_df):
"""
logger.info("Updating cases with storm bounds...")

cases_all = cases.load_ewb_events_yaml_into_case_list()
cases_all = ewb.cases.load_ewb_events_yaml_into_case_list()
cases_new = cases_all.copy()

# Update the yaml cases with storm bounds from IBTrACS data
Expand Down
3 changes: 2 additions & 1 deletion data_prep/practically_perfect_hindcast_from_lsr.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
from scipy.ndimage import gaussian_filter
from tqdm.auto import tqdm

from extremeweatherbench import inputs, utils
import extremeweatherbench.inputs as inputs
import extremeweatherbench.utils as utils


def sparse_practically_perfect_hindcast(
Expand Down
3 changes: 2 additions & 1 deletion data_prep/severe_convection_bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
import yaml
from scipy.ndimage import label

from extremeweatherbench import calc, cases
import extremeweatherbench.calc as calc
import extremeweatherbench.cases as cases

# Radius of Earth in km (mean radius)
EARTH_RADIUS_KM = 6371.0
Expand Down
3 changes: 2 additions & 1 deletion data_prep/subset_heat_cold_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
from matplotlib import dates as mdates
from mpl_toolkits.axes_grid1 import make_axes_locatable

from extremeweatherbench import cases, utils
import extremeweatherbench.cases as cases
import extremeweatherbench.utils as utils

sns.set_theme(style="whitegrid", context="talk")

Expand Down
Loading
Loading