Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion mllam_data_prep/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,8 @@ def find_config_differences(
)
args = argparser.parse_args()

assert args.f.endswith(".yaml"), "Config file must have a .yaml extension."
if not args.f.endswith(".yaml"):
raise ValueError("Config file must have a .yaml extension.")
config = Config.from_yaml_file(args.f)
import rich

Expand Down
33 changes: 21 additions & 12 deletions mllam_data_prep/ops/cropping.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
from spherical_geometry.polygon import SphericalPolygon


def _get_latlon_coords(da: xr.DataArray) -> tuple:
def _get_latlon_coords(da: Union[xr.Dataset, xr.DataArray]) -> tuple:
"""
Get the latlon coordinates of a DataArray.
Get the latlon coordinates of a Dataset or DataArray.

Parameters
----------
da : xarray.DataArray
da : xarray.Dataset or xarray.DataArray
The data.

Returns
Expand All @@ -25,7 +25,7 @@ def _get_latlon_coords(da: xr.DataArray) -> tuple:
elif "lat" in da.coords and "lon" in da.coords:
return (da.lon, da.lat)
else:
raise Exception("Could not find lat/lon coordinates in DataArray.")
raise Exception("Could not find lat/lon coordinates.")


def create_convex_hull_mask(ds: xr.Dataset, ds_reference: xr.Dataset) -> xr.DataArray:
Expand Down Expand Up @@ -53,8 +53,17 @@ def create_convex_hull_mask(ds: xr.Dataset, ds_reference: xr.Dataset) -> xr.Data
da_lon, da_lat = _get_latlon_coords(ds)
da_lon_ref, da_lat_ref = _get_latlon_coords(ds_reference)

Comment thread
pragnyanramtha marked this conversation as resolved.
assert da_lat.dims == da_lon.dims
assert da_lat_ref.dims == da_lon_ref.dims
if da_lat.dims != da_lon.dims:
raise ValueError(
"Latitude and longitude coordinates in ds must have matching "
f"dimensions, got {da_lat.dims!r} and {da_lon.dims!r}."
)
if da_lat_ref.dims != da_lon_ref.dims:
raise ValueError(
"Latitude and longitude coordinates in ds_reference must have "
f"matching dimensions, got {da_lat_ref.dims!r} and "
f"{da_lon_ref.dims!r}."
)

# latlon to (x, y, z) on unit sphere
da_ref_xyz = _latlon_to_unit_sphere_xyz(da_lat=da_lat_ref, da_lon=da_lon_ref)
Expand All @@ -65,9 +74,9 @@ def create_convex_hull_mask(ds: xr.Dataset, ds_reference: xr.Dataset) -> xr.Data
da_interior_mask = xr.apply_ufunc(
chull_lam.contains_lonlat, da_lon.load(), da_lat.load(), vectorize=True
).astype(bool)
da_interior_mask.attrs[
"long_name"
] = "contained in convex hull of source dataset (da_ref)"
da_interior_mask.attrs["long_name"] = (
"contained in convex hull of source dataset (da_ref)"
)

# Get points at edge of convex hull
chull_lam_lon, chull_lam_lat = list(chull_lam.to_lonlat())[0]
Expand Down Expand Up @@ -254,9 +263,9 @@ def distance_to_convex_hull_boundary(
da_mindist_to_ref = xr.DataArray(
mindist_to_ref, coords=ds_exterior_lat.coords, dims=ds_exterior_lat.dims
)
da_mindist_to_ref.attrs[
"long_name"
] = "minimum distance to convex hull boundary of reference dataset"
da_mindist_to_ref.attrs["long_name"] = (
"minimum distance to convex hull boundary of reference dataset"
)
da_mindist_to_ref.attrs["units"] = "radians"

if include_convex_hull_mask:
Expand Down
14 changes: 10 additions & 4 deletions mllam_data_prep/ops/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ def select_by_kwargs(ds, **coord_ranges):
sel_end = _normalize_slice_startstop(selection.end)
sel_step = _normalize_slice_step(selection.step)

assert sel_start != sel_end, "Start and end cannot be the same"
if sel_start == sel_end:
raise ValueError(
f"Start and end cannot be the same for coordinate {coord!r}: "
f"{sel_start!r}"
)

# we don't select with the step size for now, but simply check (below) that
# the step size in the data is the same as the requested step size
Expand All @@ -79,9 +83,11 @@ def select_by_kwargs(ds, **coord_ranges):
if sel_step is not None:
check_step(sel_step, coord, ds)

assert (
len(ds[coord]) > 0
), f"You have selected an empty range {sel_start}:{sel_end} for coordinate {coord}"
if len(ds[coord]) == 0:
raise ValueError(
f"You have selected an empty range {sel_start}:{sel_end} "
f"for coordinate {coord}"
)

elif isinstance(selection, list):
ds = ds.sel({coord: selection})
Expand Down
15 changes: 15 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import subprocess
import sys

import pytest
from dataclass_wizard.errors import MissingFields, UnknownJSONKey

Expand Down Expand Up @@ -129,3 +132,15 @@ def test_config_roundtrip():
assert original_config == roundtrip_config_dict
assert original_config == roundtrip_config_yaml
assert original_config == roundtrip_config_json


def test_config_main_rejects_non_yaml_path():
result = subprocess.run(
[sys.executable, "-O", "-m", "mllam_data_prep.config", "-f", "config.json"],
capture_output=True,
check=False,
text=True,
)

assert result.returncode != 0
assert ".yaml extension" in result.stderr
16 changes: 16 additions & 0 deletions tests/test_convex_hull_cropping.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import numpy as np
import pytest
import xarray as xr

import mllam_data_prep as mdp
import mllam_data_prep.config as mdp_config
Expand Down Expand Up @@ -86,6 +87,21 @@ def test_create_convex_hull_mask():
assert n_points_margin_region < n_outside


@pytest.mark.parametrize("bad_dataset", ["ds", "ds_reference"])
def test_create_convex_hull_mask_requires_matching_lat_lon_dims(bad_dataset):
valid_dataset = xr.Dataset(
coords={"lat": ("x", [0.0, 1.0]), "lon": ("x", [0.0, 1.0])}
)
invalid_dataset = xr.Dataset(
coords={"lat": ("x", [0.0, 1.0]), "lon": ("y", [0.0, 1.0])}
)
ds = invalid_dataset if bad_dataset == "ds" else valid_dataset
ds_reference = invalid_dataset if bad_dataset == "ds_reference" else valid_dataset

with pytest.raises(ValueError, match=bad_dataset):
cropping.create_convex_hull_mask(ds=ds, ds_reference=ds_reference)


@pytest.mark.parametrize("include_interior_points", [True, False])
def test_create_cropped_dataset(include_interior_points):

Expand Down
19 changes: 14 additions & 5 deletions tests/test_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,26 @@ def test_range_slice_within_range(ds):
ds


@pytest.mark.parametrize("x_start, x_end", ([-50000, -51000], [0, 500000]))
def test_error_on_empty_range(ds, x_start, x_end):
@pytest.mark.parametrize("x_start, x_end", ([-2, -1], [10, 11]))
def test_error_on_empty_range(x_start, x_end):
"""
Test if an error is thrown if the chosen range is empty
"""
y_start = -600000
y_end = -590000
ds = xr.Dataset(coords={"x": [0, 1, 2], "y": [0, 1, 2]})
y_start = 0
y_end = 2
coord_ranges = {
"x": mdp.config.Range(start=x_start, end=x_end),
"y": mdp.config.Range(start=y_start, end=y_end),
}

with pytest.raises(AssertionError):
with pytest.raises(ValueError, match="empty range"):
ds = mdp.ops.selection.select_by_kwargs(ds, **coord_ranges)


def test_error_on_equal_range_bounds():
ds = xr.Dataset(coords={"x": [0, 1, 2]})
coord_ranges = {"x": mdp.config.Range(start=1, end=1)}

with pytest.raises(ValueError, match="Start and end cannot be the same"):
mdp.ops.selection.select_by_kwargs(ds, **coord_ranges)