Source code for cmip6_downscaling.data.utils

import numpy as np
import xarray as xr
import xclim
from xarray.core.types import T_Xarray

xr.set_options(keep_attrs=True)


[docs] def to_standard_calendar(obj: T_Xarray) -> T_Xarray: """Convert a Dataset's calendar to the "standard calendar" When necessary, "missing" time points are filled in using linear interpolation. Valid input dataset calendars include: `noleap`, `365_day`, `366_day`, and `all_leap`. Parameters ---------- obj : xr.Dataset or xr.DataArray Xarray object with a `CFTimeIndex`. Returns ------- obj_new : xr.Dataset or xr.DataArray Xarray object with standard calendar. Raises ------ ValueError If an invalid calendar is supplied. """ orig_calendar = getattr(obj.indexes["time"], "calendar", "standard") if orig_calendar == "standard": return obj if orig_calendar == "360_day": raise ValueError("360_day calendar is not supported") # reindex / interpolate -- Note: .chunk was added to fix dask error obj_new = ( xclim.core.calendar.convert_calendar(obj, "standard", missing=np.nan) .chunk({'time': -1}) .interpolate_na(dim="time", method="linear") ) # reset encoding obj_new["time"].encoding["calendar"] = "standard" # sets time to datetimeindex obj_new['time'] = obj_new.indexes['time'].to_datetimeindex() return obj_new
[docs] def lon_to_180(ds): '''Converts longitude values to (-180, 180) Parameters ---------- ds : xr.Dataset Input dataset with `lon` coordinate Returns ------- xr.Dataset Copy of `ds` with updated coordinates See also -------- cmip6_preprocessing.preprocessing.correct_lon ''' ds = ds.copy() lon = ds["lon"].where(ds["lon"] < 180, ds["lon"] - 360) ds = ds.assign_coords(lon=lon) if not (ds["lon"].diff(dim="lon") > 0).all(): ds = ds.reindex(lon=np.sort(ds["lon"].data)) if "lon_bounds" in ds.variables: lon_b = ds["lon_bounds"].where(ds["lon_bounds"] < 180, ds["lon_bounds"] - 360) ds = ds.assign_coords(lon_bounds=lon_b) return ds