Skip to content

Commit

Permalink
Merge branch 'main' into feature/merge-main-into-develop
Browse files Browse the repository at this point in the history
  • Loading branch information
sandorkertesz committed Feb 18, 2025
2 parents e18b2bd + 1749a36 commit a606105
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 38 deletions.
14 changes: 14 additions & 0 deletions docs/release_notes/version_0.12_updates.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@ Version 0.12 Updates
/////////////////////////


Version 0.12.3
===============

Changes
++++++++

- ``Field.resolution()`` now returns None when the resolution cannot be determined. Previously, it failed with an assertion (:pr:`616`)

Fixes
++++++++

- Fixed issue when there was a crash during checking missing MARS credentials when calling ``from_source("mars", ...)``. It only happened when ``ecmwfapi`` was used for MARS retrievals. (:pr:`615`)


Version 0.12.2
===============

Expand Down
8 changes: 4 additions & 4 deletions src/earthkit/data/readers/geotiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ def resolution(self):
# Get width and height of pixels in units of the CRS
x, y = self._ds.rio.resolution()
crs = self._ds.rio.crs
units, factor = crs.units_factor
units, _ = crs.units_factor
# Geographic coordinate systems use latitude and longitude
if crs.is_geographic and units == "degree":
x = abs(round(x * 1_000_000) / 1_000_000)
y = abs(round(y * 1_000_000) / 1_000_000)
assert x == y, (x, y)
return x
raise NotImplementedError(f"resolution for {crs} ({units}, {factor})")
if x == y:
return x
# raise NotImplementedError(f"resolution for {crs} ({units}, {factor})")

def mars_grid(self):
raise NotImplementedError
Expand Down
11 changes: 6 additions & 5 deletions src/earthkit/data/readers/grib/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,17 @@ def resolution(self):
y = self.metadata.get("DyInDegrees")
x = round(x * 1_000_000) / 1_000_000
y = round(y * 1_000_000) / 1_000_000
assert x == y, (x, y)
return x
return x if x == y else None

if grid_type in ["lambert", "lambert_azimuthal_equal_area"]:
x = self.metadata.get("DxInMetres")
y = self.metadata.get("DyInMetres")
assert x == y, (x, y)
return str(x / 1000).replace(".", "p") + "km"
if x == y:
return str(x / 1000).replace(".", "p") + "km"
else:
return None

raise ValueError(f"Unknown gridType={grid_type}")
# raise ValueError(f"Unknown gridType={grid_type}")

def mars_grid(self):
if len(self.shape()) == 2:
Expand Down
31 changes: 14 additions & 17 deletions src/earthkit/data/sources/mars.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,23 +74,6 @@ def service(self):
if StandaloneMarsClient.enabled():
return StandaloneMarsClient(self.log)

if self.prompt:
prompt = MARSAPIKeyPrompt()
prompt.check()

try:
return self._make_service()
except Exception as e:
if ".ecmwfapirc" in str(e) or not prompt.env_configured():
LOG.warning(e)
LOG.exception(f"Could not load ecmwf api (mars) client. {e}")
prompt.ask_user_and_save()
return self._make_service()
raise
else:
return self._make_service()

def _make_service(self):
kwargs = {}
if self.log is None:
kwargs = {"log": _no_log}
Expand All @@ -104,6 +87,20 @@ def _make_service(self):
except ImportError:
raise ImportError("MARS access requires 'ecmwf-api-client' to be installed")

if self.prompt:
prompt = MARSAPIKeyPrompt()
prompt.check()

try:
return ecmwfapi.ECMWFService("mars", **kwargs)
except Exception as e:
if ".ecmwfapirc" in str(e) or not self.prompt.has_config_env():
LOG.warning(e)
LOG.exception(f"Could not load ecmwf api (mars) client. {e}")
prompt.ask_user_and_save()
else:
raise

return ecmwfapi.ECMWFService("mars", **kwargs)


Expand Down
6 changes: 5 additions & 1 deletion src/earthkit/data/sources/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def __init__(self, pattern):
self.pattern = pattern

def __call__(self, value):
assert re.fullmatch(self.pattern, value), (self.pattern, value)
if not re.fullmatch(self.pattern, value):
raise ValueError(f"Value={value} does not match pattern={self.pattern}")
return value


Expand Down Expand Up @@ -234,3 +235,6 @@ def has_api_config(self):

def validate(self, input):
return input

def rcfile_name(self):
return os.path.basename(os.path.expanduser(self.rcfile))
7 changes: 4 additions & 3 deletions src/earthkit/data/utils/metadata/dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ def gridspec(self):
return None

def resolution(self):
raise NotImplementedError("resolution is not implemented for this geography")
return None
# raise NotImplementedError("resolution is not implemented for this geography")

def mars_area(self):
return [self.north(), self.west(), self.south(), self.east()]
Expand Down Expand Up @@ -255,8 +256,8 @@ def dy(self):
def resolution(self):
x = self.dx()
y = self.dy()
assert x == y, (x, y)
return x
if x == y:
return x

def mars_grid(self):
return [self.dx(), self.dy()]
Expand Down
Binary file added tests/data/ll_10_20.grib
Binary file not shown.
4 changes: 4 additions & 0 deletions tests/grib/test_grib_geography.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,17 @@ def test_grib_projection_mercator(fl_type):
(earthkit_test_data_file("rgg_small_subarea_cellarea_ref.grib"), "O1280"),
(earthkit_test_data_file("rotated_N32_subarea.grib"), "N32"),
(earthkit_test_data_file("rotated_wind_20x20.grib"), 20),
(earthkit_test_data_file("mercator.grib"), None),
(earthkit_test_data_file("ll_10_20.grib"), None),
],
)
def test_grib_resolution(path, expected_value):
ds = earthkit.data.from_source("file", path)

if isinstance(expected_value, str):
assert ds[0].resolution == expected_value
elif expected_value is None:
assert ds[0].resolution is None
else:
assert np.isclose(ds[0].resolution, expected_value)

Expand Down
3 changes: 1 addition & 2 deletions tests/list_of_dicts/test_lod_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ def test_lod_ll(lod_distinct_ll, mode):
assert np.allclose(gr[0], lat_ref.flatten())
assert np.allclose(gr[1], lon_ref.flatten())

with pytest.raises(AssertionError):
ds[0].resolution
assert ds[0].resolution is None

assert ds[0].datetime() == {
"base_time": None,
Expand Down
9 changes: 3 additions & 6 deletions tests/list_of_dicts/test_lod_geography.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ def test_lod_geo_distinct_ll(lod_distinct_ll, mode):
assert np.allclose(gr[0], lat_ref.flatten())
assert np.allclose(gr[1], lon_ref.flatten())

with pytest.raises(AssertionError):
ds[0].resolution
assert ds[0].resolution is None

ll = ds.to_latlon()
lat = ll["lat"]
Expand Down Expand Up @@ -88,8 +87,7 @@ def test_lod_geo_ll_flat(lod_ll_flat, mode):
assert np.allclose(gr[0], lat_ref.flatten())
assert np.allclose(gr[1], lon_ref.flatten())

with pytest.raises(NotImplementedError):
ds[0].resolution
assert ds[0].resolution is None

ll = ds.to_latlon()
lat = ll["lat"]
Expand Down Expand Up @@ -128,8 +126,7 @@ def test_lod_geo_ll_2D(request, data, mode):
assert np.allclose(gr[0], lat_ref.flatten())
assert np.allclose(gr[1], lon_ref.flatten())

with pytest.raises(NotImplementedError):
ds[0].resolution
assert ds[0].resolution is None

ll = ds.to_latlon()
lat = ll["lat"]
Expand Down

0 comments on commit a606105

Please sign in to comment.