Skip to content

Commit adcb28d

Browse files
committed
Raise warning if no time coords found with decode_times
1 parent 1a0afb4 commit adcb28d

File tree

2 files changed

+65
-6
lines changed

2 files changed

+65
-6
lines changed

tests/test_dataset.py

+44
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,28 @@ def setup(self, tmp_path):
2727
dir.mkdir()
2828
self.file_path = f"{dir}/file.nc"
2929

30+
def test_raises_warning_if_decode_times_but_no_time_coords_found(self, caplog):
31+
ds = generate_dataset(decode_times=False, cf_compliant=True, has_bounds=True)
32+
ds = ds.drop_dims("time")
33+
ds.to_netcdf(self.file_path)
34+
35+
result = open_dataset(self.file_path)
36+
expected = generate_dataset(
37+
decode_times=False,
38+
cf_compliant=True,
39+
has_bounds=True,
40+
)
41+
expected = expected.drop_dims("time")
42+
43+
assert result.identical(expected)
44+
assert (
45+
"No time coordinates were found in this dataset to decode. Make sure time "
46+
"coordinates exist and their CF 'axis' or 'standard_name' attribute is set "
47+
"(e.g., ds['time'].attrs['axis'] = 'T' or "
48+
"ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding "
49+
"with `decode_time()` again."
50+
) in caplog.text
51+
3052
def test_skip_decoding_time_explicitly(self):
3153
ds = generate_dataset(decode_times=False, cf_compliant=True, has_bounds=True)
3254
ds.to_netcdf(self.file_path)
@@ -567,6 +589,28 @@ def setUp(self, tmp_path):
567589
self.file_path1 = f"{dir}/file1.nc"
568590
self.file_path2 = f"{dir}/file2.nc"
569591

592+
def test_raises_warning_if_decode_times_but_no_time_coords_found(self, caplog):
593+
ds = generate_dataset(decode_times=False, cf_compliant=True, has_bounds=True)
594+
ds = ds.drop_dims("time")
595+
ds.to_netcdf(self.file_path1)
596+
597+
result = open_mfdataset(self.file_path1)
598+
expected = generate_dataset(
599+
decode_times=False,
600+
cf_compliant=True,
601+
has_bounds=True,
602+
)
603+
expected = expected.drop_dims("time")
604+
605+
assert result.identical(expected)
606+
assert (
607+
"No time coordinates were found in this dataset to decode. Make sure time "
608+
"coordinates exist and their CF 'axis' or 'standard_name' attribute is set "
609+
"(e.g., ds['time'].attrs['axis'] = 'T' or "
610+
"ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding "
611+
"with `decode_time()` again."
612+
) in caplog.text
613+
570614
def test_skip_decoding_times_explicitly(self):
571615
ds1 = generate_dataset(decode_times=False, cf_compliant=False, has_bounds=True)
572616
ds1.to_netcdf(self.file_path1)

xcdat/dataset.py

+21-6
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ def open_dataset(
100100
ds = xr.open_dataset(path, decode_times=False, **kwargs) # type: ignore
101101

102102
if decode_times:
103-
ds = decode_time(ds)
103+
try:
104+
ds = decode_time(ds)
105+
except KeyError as e:
106+
logger.warning(e)
104107

105108
ds = _postprocess_dataset(ds, data_var, center_times, add_bounds, lon_orient)
106109

@@ -243,6 +246,13 @@ def decode_time(dataset: xr.Dataset) -> xr.Dataset:
243246
Dataset with decoded time coordinates and time bounds (if they exist) as
244247
``cftime`` objects.
245248
249+
Raises
250+
------
251+
KeyError
252+
If time coordinates are not found in the dataset, either because they
253+
don't exist at all or they can't be mapped to via CF attributes (e.g.,
254+
'axis' or 'standard_name').
255+
246256
Notes
247257
-----
248258
Time coordinates are represented by ``cftime.datetime`` objects because
@@ -306,10 +316,11 @@ def decode_time(dataset: xr.Dataset) -> xr.Dataset:
306316

307317
if len(coord_keys) == 0:
308318
raise KeyError(
309-
"Unable to map to time coordinates in this dataset to perform decoding. "
310-
"Make sure that the time coordinates have the CF 'axis' or 'standard_name' "
311-
"attribute set (e.g., ds['time'].attrs['axis'] = 'T' or "
312-
"ds['time'].attrs['standard_name'] = 'time'), and try decoding again. "
319+
"No time coordinates were found in this dataset to decode. Make sure time "
320+
"coordinates exist and their CF 'axis' or 'standard_name' attribute is set "
321+
"(e.g., ds['time'].attrs['axis'] = 'T' or "
322+
"ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding "
323+
"with `decode_time()` again."
313324
)
314325

315326
for key in coord_keys:
@@ -376,6 +387,7 @@ def _preprocess(
376387
The Dataset.
377388
callable : Optional[Callable], optional
378389
A user specified optional callable function for preprocessing.
390+
379391
Returns
380392
-------
381393
xr.Dataset
@@ -387,7 +399,10 @@ def _preprocess(
387399
ds_new = callable(ds)
388400

389401
if decode_times:
390-
ds_new = decode_time(ds_new)
402+
try:
403+
ds_new = decode_time(ds_new)
404+
except KeyError as e:
405+
logger.warning(e)
391406

392407
return ds_new
393408

0 commit comments

Comments
 (0)