Source code for pycif.plugins.datastreams.fluxes.dalecbethy.read
import numpy as np
import xarray as xr
from .....utils.check.errclass import CifError
from .....utils.hdf5 import _hdf5_lock
[docs]
def read(
self,
name,
varnames,
dates,
files,
interpol_flx=False,
tracer=None,
model=None,
ddi=None,
**kwargs
):
"""Get D&B meteorological forcing values from its dynamic forcing file.
For each requested hourly period, finds the matching ``time`` record in
the file and extracts the row of ``var2extract`` for D&B's active
sample points (``tracer.domain.active``, set by
:func:`pycif.plugins.domains.dalecbethy.read_domain.read_grid`), so that
the returned data lines up 1-to-1 with ``tracer.domain.zlon``/``zlat``.
D&B's own ``time`` records mark the *end* of each hourly period (see
``pycif.plugins.datastreams.fluxes.dalecbethy.fetch.fetch``, which
builds ``period == [hh - 1h, hh]`` from each ``hh`` record), so periods
are matched on ``period[1]``, not ``period[0]``.
Args:
self: the fluxes Plugin.
name (str): name of the component.
varnames (list[str] or str): variable name(s) to read; ``name`` is
used if ``varnames`` is empty.
dates (list): list of the date intervals to extract.
files (list): list of files matching ``dates``.
interpol_flx (bool): unused, kept for interface compatibility.
tracer: the tracer Plugin, giving access to ``domain.active``.
model: unused, kept for interface compatibility.
ddi: unused, kept for interface compatibility.
**kwargs: unused, kept for interface compatibility.
Returns:
xr.DataArray: the forcing data with dimensions
``(time, lev, lat, lon)`` (``lev`` and ``lat`` of size 1).
Raises:
CifError: if ``tracer.domain`` has no ``active`` attribute (i.e. its
grid was not read through ``pycif.plugins.domains.dalecbethy``),
or if a requested hour cannot be found in a file.
"""
var2extract = varnames if varnames != "" else name
if not hasattr(tracer.domain, "active"):
raise CifError(
f"D&B fluxes tracer {tracer.name} requires a 'dalecbethy' "
f"domain (with an 'active' sample-point selection) to align "
f"its 'ng'-indexed forcing rows with the tracer's own grid."
)
active = tracer.domain.active
trcr_flx = []
for period, ff in zip(dates, files):
with _hdf5_lock:
with xr.open_dataset(ff) as ds:
(hour_idx,) = np.where(
ds["time"].values == np.datetime64(period[1]))
if hour_idx.size == 0:
raise CifError(
f"Could not find time record {period[1]} in D&B "
f"dynamic forcing file '{ff}' for tracer "
f"{tracer.name}."
)
data = (
ds[var2extract]
.isel(time=hour_idx[0])
.values[active]
.astype(float)
)
trcr_flx.append(data)
xmod = xr.DataArray(
np.array(trcr_flx)[:, np.newaxis, np.newaxis, :],
coords={"time": np.array(dates)[:, 0]},
dims=("time", "lev", "lat", "lon"),
)
return xmod