import numpy as np
import xarray as xr
import netCDF4 as nc
from .times_in_wrf_file import times_in_wrf_file
[docs]
def read(
self,
trcr,
varname,
in_dates,
in_files,
comp_type,
tracer,
model,
ddi,
**kwargs
):
"""Read fluxes from files and load them into a xarray.DataArray
Inputs:
---------
Arguments as in plugins/transforms/system/fromcontrol/forward.py.
trcr: string
Name in the yaml
varname: string
Variable name in file. In yaml it's "varname". If it's not
defined in the yaml it's empty here.
in_dates: list of datetime.datetime objects
All input dates
in_files: list of strings
For each in_dates, the file where the flux is found
comp_type: string
Name of component in yaml, i.e. level above parameter.
Currently "flux" in my config_wrfchem_explanations.yml.
Probably won't use it.
tracer : Plugin flux
Full flux object, with everything in the yaml. Use this
instead of the self in read.py because that self can be
modified. Same with write.
model: model plugin
So you can use e.g. its domain subplugin
ddi: datetime.datetime?
Start of model period, probably won't use it.
**kwargs:
Ignore, will be removed.
Ouputs:
---------
xmod: xarray.DataArray
Flux data.
Dimensions: (time, vertical levels, latitude, longitude)
Coordinates in increasing order.
VERSION HISTORY (before incremental git commit messages)
2021-09-20 freum Wrote it.
2021-09-17 freum Changed arguments to the ones in
pycif/plugins/transforms/system/fromcontrol/forward.py
2021-08-20 freum Original code from flux_plugin_template, put a
NotImplementedError at the beginning.
"""
fluxes = []
dates = []
# Loop over each input date
for in_period, in_file in zip(in_dates, in_files):
# Get time index in file to read
times = times_in_wrf_file(in_file)
ind = [n for n, t in enumerate(times) if t==in_period[0]]
# Complain if requested date not found exactly once in file
if len(ind)!=1:
fmt = "%Y-%m-%d %H:%M:%S"
in_date_str = in_period[0].strftime(fmt)
if len(ind)==0:
# This case is probably impossible by design
times_str_l = [time.strftime(fmt) for time in times]
times_str = ", ".join(t_str_l)
msg = "in_date {} not found in {}. Dates in file: {}."
raise ValueError(msg.format(in_date_str, in_file, times_str))
elif len(ind)>1:
msg = "in_date {} found more than once in file {}."
raise ValueError(msg.format(in_date_str, in_file))
# Read data
ncf = nc.Dataset(in_file, "r")
dat = ncf[varname][ind, ...]
ncf.close()
# Check dimensions. Ignore levels for now (if I recall
# correctly, the files don't have to match kemit exactly).
domain = model.domain
# In the case of the unstructured wrf domain, flatten the lat/lon
# dimensions of the input data
if getattr(domain, "unstructured_domain", False):
dat = dat.reshape(dat.shape[:2] + (1, np.prod(dat.shape[2:])))
dat_shape = [dat.shape[n] for n in [0, 2, 3]]
required_shape = [1, domain.nlat, domain.nlon]
if dat_shape!=required_shape:
msg_fmt = "File {}, variable {}: Expected shape {}, got " + \
"{} (levels are ignored here)."
msg = msg_fmt.format(in_file, varname, str(required_shape),
str(dat_shape))
raise ValueError(msg)
# Collect data into list
fluxes.append(dat)
dates.append(in_period[0])
# Fill datastore
xmod = xr.DataArray(
np.concatenate(fluxes, axis=0),
coords={"time": dates},
dims=("time", "lev", "lat", "lon"),
)
return xmod