Skip to content

Commit

Permalink
Update decode_time_units()
Browse files Browse the repository at this point in the history
- Rename to `decode_non_cf_time()` and remove logic for cf unit decoding
- Fix incorrect start date for pandas date range by adding offset from first coordinate point

Refactor function and variable names
- Update `xcdat_infer` attr from None to "None" since `to_netcdf` does not support None type
- Update fixtures for non cf time bounds and `generate_dataset()`

Update `decode_non_cf_time()` to use offsets correctly
- Using pd.date_range() is incorrect because it assumes no gaps or missing data. It also resets offsets to beginning of the month and year and does not consider leap years
- pd.DataOffset considers relative arithmetic operations based on the calendar

Update `decode_non_cf_time()` to handle time bounds
- Update tests for `decode_non_cf_time()`

Add functions to `__init__.py`
- Update time fixtures with correct attributes

Add `_preprocess_non_cf_dataset()`
- Add test for callable in `_preprocess_non_cf_dataset`
  • Loading branch information
tomvothecoder committed Dec 2, 2021
1 parent ec6e20c commit 10ffc6b
Show file tree
Hide file tree
Showing 5 changed files with 810 additions and 478 deletions.
3 changes: 2 additions & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ Top-level API

dataset.open_dataset
dataset.open_mfdataset
dataset.has_cf_compliant_time
dataset.decode_non_cf_time
dataset.infer_or_keep_var
dataset.decode_time_units
dataset.get_inferred_var

.. currentmodule:: xarray
Expand Down
50 changes: 25 additions & 25 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,20 @@
],
dims=["time"],
attrs={
"axis": "T",
"long_name": "time",
"standard_name": "time",
"axis": "T",
},
)
time_non_cf = xr.DataArray(
data=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
dims=["time"],
attrs={
"units": "months since 2000-01-01",
"calendar": "standard",
"axis": "T",
"long_name": "time",
"standard_name": "time",
"axis": "T",
},
)

Expand Down Expand Up @@ -72,18 +74,18 @@
time_bnds_non_cf = xr.DataArray(
name="time_bnds",
data=[
[datetime(1999, 12, 16, 12), datetime(2000, 1, 16, 12)],
[datetime(2000, 1, 16, 12), datetime(2000, 2, 15, 12)],
[datetime(2000, 2, 15, 12), datetime(2000, 3, 16, 12)],
[datetime(2000, 3, 16, 12), datetime(2000, 4, 16)],
[datetime(2000, 4, 16), datetime(2000, 5, 16, 12)],
[datetime(2000, 5, 16, 12), datetime(2000, 6, 16)],
[datetime(2000, 6, 16), datetime(2000, 7, 16, 12)],
[datetime(2000, 7, 16, 12), datetime(2000, 8, 16, 12)],
[datetime(2000, 8, 16, 12), datetime(2000, 9, 16)],
[datetime(2000, 9, 16), datetime(2000, 10, 16, 12)],
[datetime(2000, 10, 16, 12), datetime(2000, 11, 16)],
[datetime(2000, 11, 16), datetime(2000, 12, 16)],
[-1, 0],
[0, 1],
[1, 2],
[2, 3],
[3, 4],
[4, 5],
[5, 6],
[6, 7],
[7, 8],
[8, 9],
[9, 10],
[10, 11],
],
coords={"time": time_non_cf},
dims=["time", "bnds"],
Expand Down Expand Up @@ -172,19 +174,18 @@ def generate_dataset(cf_compliant: bool, has_bounds: bool) -> xr.Dataset:
)

if cf_compliant:
ds = ds.assign({"time_bnds": time_bnds.copy()})
ds = ds.assign_coords({"time": time_cf.copy()})
ds.coords["time"] = time_cf.copy()
ds["time_bnds"] = time_bnds.copy()
elif not cf_compliant:
ds = ds.assign({"time_bnds": time_bnds_non_cf.copy()})
ds = ds.assign_coords({"time": time_non_cf.copy()})
ds["time"] = ds.time.assign_attrs(units="months since 2000-01-01")
ds.coords["time"] = time_non_cf.copy()
ds["time_bnds"] = time_bnds_non_cf.copy()

# If the "bounds" attribute is included in an existing DataArray and
# added to a new Dataset, it will get dropped. Therefore, it needs to be
# assigned to the DataArrays after they are added to Dataset.
ds["lat"] = ds.lat.assign_attrs(bounds="lat_bnds")
ds["lon"] = ds.lon.assign_attrs(bounds="lon_bnds")
ds["time"] = ds.time.assign_attrs(bounds="time_bnds")
ds["lat"].attrs["bounds"] = "lat_bnds"
ds["lon"].attrs["bounds"] = "lon_bnds"
ds["time"].attrs["bounds"] = "time_bnds"

elif not has_bounds:
ds = xr.Dataset(
Expand All @@ -193,9 +194,8 @@ def generate_dataset(cf_compliant: bool, has_bounds: bool) -> xr.Dataset:
)

if cf_compliant:
ds = ds.assign_coords({"time": time_cf.copy()})
ds.coords["time"] = time_cf.copy()
elif not cf_compliant:
ds = ds.assign_coords({"time": time_non_cf.copy()})
ds["time"] = ds.time.assign_attrs(units="months since 2000-01-01")
ds.coords["time"] = time_non_cf.copy()

return ds
Loading

0 comments on commit 10ffc6b

Please sign in to comment.