Source code for pycif.plugins.datastreams.fields.netcdf_cams.read
import datetime
import calendar
import os
import pandas as pd
import numpy as np
import xarray as xr
from netCDF4 import Dataset
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,
tracer=None,
ddi=None,
**kwargs
):
"""Get BCs from raw CAMS files and load them into a pyCIF variable.
For each requested date, computes the time index within the monthly
file from the file's number of time steps, reads the variable, and
flips the latitude axis to increasing order (and the vertical axis
if ``tracer.flip_level`` is set) as needed.
Args:
self: the BC Plugin
name: the name of the component
varnames: variable name to extract if different from ``name``
dates: list of ``[start, end]`` date pairs to extract
files: list of file paths matching ``dates``
interpol_flx: unused, accepted for interface compatibility
comp_type: unused, accepted for interface compatibility
tracer: the fields Plugin; ``tracer.flip_level`` controls whether
the vertical axis is flipped
ddi: must not be ``None``; only used to validate the call, not
otherwise referenced
Returns:
xarray.DataArray with dims ``(time, lev, lat, lon)``.
Raises:
CifError: if ``ddi`` is ``None``.
"""
if ddi is None:
raise CifError("CAMS netCDF read function was called "
"without specifying ddi")
# Variable name to extract
var2extract = name
if varnames != "":
var2extract = varnames
# Reading fields for periods within the simulation window
xout = []
opened_file = ""
for dd, dd_file in zip(dates, files):
with _hdf5_lock:
# Avoid opening the file for all dates
if dd_file != opened_file:
ds = xr.open_dataset(dd_file)
opened_file = dd_file
ntimes = ds.dims["time"]
freq = pd.DatetimeIndex([dd[0]]).days_in_month[0] * 24 / ntimes
date_end = ds["time"].to_pandas().dt.to_pydatetime()[-1]
date_index = \
ntimes - 1 - int((date_end - dd[0]) /
datetime.timedelta(hours=freq))
# bottom of the atmosphere = at the beginning of the table
lat = ds['latitude']
conc = ds[var2extract].values[date_index]
if lat[1] < lat[0] and conc.ndim == 4:
conc = conc[:, :, ::-1, :]
elif lat[1] < lat[0] and conc.ndim == 3:
conc = conc[:, ::-1, :]
# Swap levels if required to
if getattr(tracer, "flip_level", False):
if conc.ndim == 4:
conc = conc[:, ::-1]
elif conc.ndim == 3:
conc = conc[::-1]
# Append to datastore
xout.append(conc)
xmod = xr.DataArray(
np.array(xout),
coords={"time": np.array(dates)[:, 0]},
dims=("time", "lev", "lat", "lon"),
)
return xmod