Source code for pycif.plugins.datastreams.fields.lmdz_chemfield_reg.read
from __future__ import annotations
import datetime
from os import PathLike
import pandas as pd
import xarray as xr
from .....utils.check.errclass import CifValueError
from .....utils.hdf5 import _hdf5_lock
[docs]
def read(
self,
name: str,
varnames: str,
dates: list[tuple[datetime.datetime, datetime.datetime]],
files: list[str | PathLike],
ddi: datetime.datetime | None = None,
**kwargs,
):
"""Read LMDz chemical field data (regular grid) into a pyCIF DataArray.
Opens each distinct file in ``files`` once (validating that the
requested variable exists), selects the day index (relative to the
file's month, computed from ``ddi``) for each requested date,
concatenates the selected time steps along ``time_counter``, expands a
missing vertical dimension (for deposition-velocity/surface-only
fields), renames dimensions to pyCIF's ``(time, lev, lat, lon)``
convention, drops non-time coordinates, and transposes accordingly.
Args:
self: The field/tracer Plugin.
name: Name of the component; used as fallback variable name.
varnames: Name of the variable to read; if empty, ``name`` is used
instead.
dates: List of ``(start, end)`` date tuples to extract, matching
``files``.
files: List of files matching ``dates``; each distinct file is
opened only once.
ddi: Reference date used to compute each date's day-of-month index
within its file. Mandatory.
**kwargs: Unused.
Returns:
xarray.DataArray: A 4-dimensional ``(time, lev, lat, lon)`` array.
Raises:
CifValueError: If ``ddi`` is not given, or if the requested
variable is not found in a file.
"""
varnames = varnames if varnames else name
if ddi is None:
raise CifValueError("'ddi' argument is required")
da_list = []
file_ref = ""
da = None
for (di, _), file_path in zip(dates, files):
if file_path != file_ref:
file_ref = file_path
with _hdf5_lock:
with xr.open_dataset(file_path) as ds:
if varnames not in ds:
raise CifValueError(
f"Variable '{varnames}' not found in '{file_path}'"
)
da = ds[varnames]
if da is None:
raise CifValueError(f"Error while reading '{file_path}'")
# Assume monthly files with daily resolution
day_index = (di - ddi).days + ddi.day - 1
da_list.append(da.isel(time_counter=[day_index]))
xmod = xr.concat(da_list, dim="time_counter")
# Adding vertical dimension for deposition velocity fields
if "presnivs" not in xmod.dims:
xmod = xmod.expand_dims("presnivs", axis=1)
xmod = xmod.rename(time_counter="time", presnivs="lev")
# Dropping coordinates
for coord_name in xmod.coords:
if coord_name != "time":
xmod = xmod.drop(coord_name)
# Reordering dimensions
xmod = xmod.transpose("time", "lev", "lat", "lon")
return xmod