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

import datetime
import os

import numpy as np
import xarray as xr
from netCDF4 import Dataset
from logging import debug

from .....utils.netcdf import readnc
from .....utils.check.errclass import CifError
from .....utils.hdf5 import _hdf5_lock


[docs] def read( self, name, varnames, dates, files, interpol_flx=False, comp_type=None, ddi=None, **kwargs ): """Read CHIMERE INI_CONCS/BOUN_CONCS data and load it into a pyCIF DataArray. For ``comp_type == "inicond"``, reads the variable from the single ``INI_CONCS``-style file in ``files``. For ``"latcond"``/``"topcond"``, reads the ``lat_conc``/``top_conc`` variable from each ``BOUN_CONCS`` file in turn, looks up the matching species and date index (falling back to an index derived from ``ddi`` if the exact date string is not found), and fills the corresponding slice with zeros if the species is absent from the file. Args: self: The field/tracer Plugin. name: Name of the component (used as fallback variable name). varnames: Name of the variable/species to read; if empty, ``name`` is used instead. dates: List of dates to extract, matching ``files``. files: List of files matching ``dates``. interpol_flx: Unused. comp_type: Type of boundary condition to read: ``"inicond"``, ``"latcond"`` or ``"topcond"``. ddi: Reference date used to compute a fallback time index when the exact date string cannot be found in a ``BOUN_CONCS`` file. **kwargs: Unused. Returns: xarray.DataArray: A 4-dimensional ``(time, lev, lat, lon)`` array. Raises: CifError: If ``comp_type`` is ``None``, unrecognized, or if ``ddi`` is needed but not given while a date cannot be matched exactly. """ var2extract = varnames if varnames != "" else name # Check the type of limit condition to check if comp_type is None: raise CifError( "Trying to read limit conditions for CHIMERE, " "but did not specify the type" ) # Read INI_CONCS if comp_type == "inicond": ic_file = files[0] with _hdf5_lock: ds = xr.open_dataset(ic_file) data = ds[var2extract][:] # Differentiate case when inicond or end files if "Time" not in data.dims: data = data.values[np.newaxis, :] else: data = data.values xmod = xr.DataArray( data, coords={"time": [np.min(dates)]}, dims=("time", "lev", "lat", "lon"), ) # Read Lateral boundary conditions elif comp_type in ["latcond", "topcond"]: # Reading required field files trcr_bc = [] out_dates = [] for dd, ff in zip(dates, files): # Getting the data spec = "lat_conc" if comp_type == "latcond" else "top_conc" data, times, specs = readnc(ff, [spec, "Times", "species"]) # Get the correct date and species index try: ispec = [ "".join(c).strip() for c in specs.astype(str) ].index(var2extract) except ValueError: ispec = -1 try: idate = [ datetime.datetime.strptime("".join(d), "%Y-%m-%d_%H:%M:%S") for d in times.astype(str) ].index(dd[0]) except ValueError: debug(f"Try to read date {dd[0]} in file {ff}, but not available. Using index from {ddi} to fetch correct date") if ddi is None: raise CifError(f"Could not find correct index in {ff} because ddi was not given") idate = int((dd[0] - ddi).total_seconds() // 3600) # Appending if ispec == -1: #### ajouter and fill_with_zeros: + voir si on met vraiment des 0 ou juste rien du tout = selon ce que fait CHIMERE ensuite trcr_bc.append(data[idate, ..., 0] * 0.0) else: trcr_bc.append(data[idate, ..., ispec]) out_dates.append(dd[0]) # Putting the data into an xarray # Adding an empty latitude axis if comp_type == "latcond": xout = np.array(trcr_bc)[..., np.newaxis, :] else: xout = np.array(trcr_bc)[:, np.newaxis, ...] xmod = xr.DataArray( xout, coords={"time": out_dates}, dims=("time", "lev", "lat", "lon") ) else: raise CifError( f"Could not recognize the type of boundary condition to read in CHIMERE: {comp_type}" ) return xmod