Source code for pycif.plugins.datastreams.fields.grib2_ecmwf.read

from logging import debug, warning

import numpy as np
import xarray as xr

from .utils import GribDataset, get_grid_type, get_jscan


[docs] def read( self, name, varnames, dates, files, interpol_flx=False, comp_type=None, tracer=None, **kwargs, ): """Read a variable from ECMWF GRIB files and load it into a pyCIF DataArray. For each date, opens the associated GRIB file(s) via :class:`~pycif.plugins.datastreams.fields.grib2_ecmwf.utils.GribDataset`, flips the latitude axis if the file's scan direction requires it, flips the vertical axis for non-surface fields, decumulates the field (using the two straddling files fetched for that purpose) if ``tracer.decumul`` is set, and optionally expands surface pressure into a full 3D pressure (or pressure-thickness) field. Args: self: The field/tracer Plugin. name: Name of the component (unused directly here). varnames: Name of the GRIB variable to read. dates: List of date entries (each a ``[date, ...]``-like sequence) to extract, matching ``files``. files: List of file-group entries matching ``dates``; each entry is itself a list of one (regular) or two (decumulation) file paths. interpol_flx: Unused. comp_type: Unused. tracer: Tracer/component configuration (``filter_by_keys_dict``, ``surface``, ``decumul``, ``expand_psurf``, ``pressure_thickness``, ``domain``, etc.). **kwargs: Unused. Returns: xarray.DataArray: A 4-dimensional ``(time, lev, lat, lon)`` array. """ xout = [] outdates = [] for dd, dd_file in zip(dates, files): spec_cum = [] for ddi_file in dd_file: ds = GribDataset( ddi_file, filter_by_keys=tracer.filter_by_keys_dict, ) speci = ds[varnames] grid_type = get_grid_type(ddi_file, tracer.filter_by_keys_dict) if grid_type == "regular": # Flip latitudes if jscan = 0 jscan = get_jscan(ddi_file, tracer.filter_by_keys_dict) if jscan == 0: speci = speci[..., ::-1, :] # Flip levels if not surface field if not tracer.surface: speci = speci[::-1, ...] spec_cum.append(speci) # decumulation if decumul if tracer.decumul: debug(f"Decumulation done for date {dd[0]} and file {dd_file}") if len(spec_cum) > 1: spec = spec_cum[1] - spec_cum[0] else: warning( f"impossible DECUMULATION ? for date {dd[0]} and file {dd_file}" ) spec = spec_cum[0] else: spec = spec_cum[0] xout.append(spec) outdates.append(dd[0]) xout = np.array(xout) if grid_type != "regular": xout = xout[..., np.newaxis, :] if tracer.surface: xout = xout[:, np.newaxis, ...] else: xout = xout # Expand surface if tracer.expand_psurf: domain = tracer.domain sigma_a = domain.sigma_a[np.newaxis, :, np.newaxis, np.newaxis] sigma_b = domain.sigma_b[np.newaxis, :, np.newaxis, np.newaxis] pinterface = np.exp(xout) * sigma_b + sigma_a xout = 0.5 * (pinterface[:, 1:] + pinterface[:, :-1]) # Pressure difference if tracer.pressure_thickness: xout = np.diff(pinterface, axis=1) xmod = xr.DataArray( xout, coords={"time": outdates}, dims=("time", "lev", "lat", "lon"), ) return xmod