Source code for pycif.plugins.datastreams.fluxes.chimere.fetch
import os
import datetime
import pandas as pd
import xarray as xr
import itertools
from .....utils import path
from .....utils.classes.setup import Setup
from .....utils.check.errclass import CifError
from .....utils.hdf5 import _hdf5_lock
[docs]
def fetch(ref_dir, ref_file, input_interval, target_dir, tracer=None, **kwargs):
"""Fetch CHIMERE AEMISSIONS/BEMISSIONS files covering the interval.
Builds a date range at ``tracer.file_freq``, links each existing
per-period file into ``target_dir`` with hourly sub-dates. If the linked
file declares a ``bottom_top`` dimension different from the domain's
current number of levels, ``tracer.domain`` is rebuilt with the file's
vertical level count (horizontal geometry copied as-is, sigma
coefficients truncated to the new number of levels).
Args:
ref_dir (str): directory where the original files are found.
ref_file (str): (template) name of the original files.
input_interval (list): simulation interval, as a list of the two
bounding dates.
target_dir (str): directory where links to the original files are
created.
tracer: the tracer Plugin, giving access to ``file_freq``,
``name`` and ``domain``.
**kwargs: unused, kept for interface compatibility.
Returns:
(dict, dict): ``list_files`` and ``list_dates``.
list_files: for each date that begins a period, a list containing
the names of the files that are available for the dates within
this period.
list_dates: for each date that begins a period, a list containing
the date intervals matching the files listed in ``list_files``.
Raises:
CifError: if ``tracer.file_freq`` is not set, or if no file matching
``ref_dir``/``ref_file`` is found over the requested interval.
"""
if tracer.file_freq == "":
raise CifError(
f"File frequency is not set for tracer {tracer.name} "
f"while it is required to fetch files from {file}"
)
list_period_dates = \
pd.date_range(input_interval[0], input_interval[1], freq=tracer.file_freq)
list_dates = {}
list_files = {}
for dd in list_period_dates:
file = dd.strftime(f"{ref_dir}/{ref_file}")
if os.path.isfile(file):
file_hours = pd.date_range(
dd, dd + pd.to_timedelta(tracer.file_freq), freq="1h")
list_dates[dd] = [[hh, hh + datetime.timedelta(hours=1)]
for hh in file_hours]
list_files[dd] = (len(file_hours) * [file])
# Fetching
target_file = f"{target_dir}/{os.path.basename(file)}"
path.link(file, target_file)
# Raise exception if no file was found
if not list(itertools.chain(*list_files.values())):
raise CifError(
f"Could not find any file fitting the requested structure:\nPlease check your informations: \n - ref_dir: {ref_dir}\n - ref_file: {ref_file}\n - date_range: {input_interval}\n - file_freq: {tracer.file_freq}\nThis set-up leads to the following dates and files being looped on:\n"
+ "\n".join([dd.strftime(f" - {dd}: {ref_dir}/{ref_file}")
for dd in list_period_dates])
)
# Alter vertical domain depending on input files
# if bottom_top dimension is available
file_ref = list(itertools.chain(*list_files.values()))[0]
nlevemis = 0
try:
with _hdf5_lock:
nlevemis = xr.open_dataset(file_ref).sizes["bottom_top"]
except KeyError:
pass
if nlevemis > 0:
domain_in = tracer.domain
if domain_in.nlev != nlevemis:
domain_out = Setup.load_registered(
domain_in.plugin.name, domain_in.plugin.version,
"domain", plg_orig=domain_in
)
domain_out.nlon = domain_in.nlon
domain_out.nlat = domain_in.nlat
domain_out.zlon = domain_in.zlon
domain_out.zlat = domain_in.zlat
domain_out.zlonc = domain_in.zlonc
domain_out.zlatc = domain_in.zlatc
domain_out.nlon_side = domain_in.nlon_side
domain_out.nlat_side = domain_in.nlat_side
domain_out.zlonc_side = domain_in.zlonc_side
domain_out.zlatc_side = domain_in.zlatc_side
domain_out.zlon_side = domain_in.zlon_side
domain_out.zlat_side = domain_in.zlat_side
# Read nlevemis from one of the available files
domain_out.pressure_unit = domain_in.pressure_unit
domain_out.nlev = nlevemis
domain_out.sigma_a = domain_in.sigma_a[:domain_out.nlev + 1]
domain_out.sigma_b = domain_in.sigma_b[:domain_out.nlev + 1]
domain_out.sigma_a_mid = domain_in.sigma_a_mid[:domain_out.nlev]
domain_out.sigma_b_mid = domain_in.sigma_b_mid[:domain_out.nlev]
tracer.domain = domain_out
return list_files, list_dates