Source code for pycif.plugins.datastreams.fluxes.edgar_v5.fetch

import datetime
import glob
import os
import pandas as pd
import xarray as xr
import numpy as np
import glob
from netCDF4 import Dataset, num2date

from .....utils import path
from .....utils.hdf5 import _hdf5_lock
from logging import info, debug


[docs] def fetch(ref_dir, ref_file, date_interval, target_dir, tracer=None, **kwargs): """Fetch EDGAR v5 yearly files, falling back to the closest available year. Expands ``date_interval`` to include full years, then scans all files matching ``ref_dir``/``ref_file`` between 1900 and 2100 to determine, for each requested year, the closest available year at or before it (the ``closest_year`` behavior is effectively always applied by this lookup). The resolved file is linked into ``target_dir``; if it has a ``time`` variable, it is read to build the per-record ``[start, end]`` date pairs actually covered, otherwise the whole file is treated as covering the full requested year. Args: ref_dir (str): directory where the original files are found. ref_file (str): (template) name of the original files. date_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; unused directly but kept for interface compatibility. **kwargs: unused, kept for interface compatibility. Returns: (dict, dict): ``list_files`` (``tmp_files``) and ``list_dates`` (``tmp_dates``). list_files: for each requested year, a list containing the name of the resolved file repeated once per covered date interval. list_dates: for each requested year, a list of ``[start, end]`` date intervals covered by the resolved file. """ # Reshape input interval to include full years datei, datef = date_interval datei = datetime.datetime(year=datei.year, month=1, day=1) datef = datetime.datetime(year=datef.year + 1, month=1, day=1) list_dates = pd.date_range(datei, datef, freq="1YS") # Find all available dates matching the format provided by the user list_dates_avail = np.array([ d.to_pydatetime() for d in pd.date_range("1900", "2100", freq="1YS") if os.path.isfile( d.strftime(f"{ref_dir}/{ref_file}")) ]) list_files_avail = np.array([ d.strftime(f"{ref_dir}/{ref_file}") for d in pd.date_range("1900", "2100", freq="1YS") if os.path.isfile( d.strftime(f"{ref_dir}/{ref_file}")) ]) list_files_avail = list_files_avail[np.argsort(list_dates_avail)] list_dates_avail = np.sort(list_dates_avail) # Loop over years to find correct file tmp_files = {} tmp_dates = {} for dd in list_dates: deltas = dd - list_dates_avail if np.any(deltas >= datetime.timedelta(0)): delta_max = np.min(deltas[deltas >= datetime.timedelta(0)]) indout = np.where(deltas == delta_max)[0][0] else: indout = 0 file = list_files_avail[indout] # Check if "time" is in variables # Do not do it with open_dataset which is slow with big files... with _hdf5_lock: with Dataset(file, "r") as f: available_time = "time" in f.variables if available_time: debug(f"Fetching times for date {dd} from {file}") with _hdf5_lock: with Dataset(file, "r") as f: times = f.variables["time"] dates = num2date(times[:], times.units, only_use_python_datetimes=True, only_use_cftime_datetimes=False) dt = np.unique(np.diff(dates))[0] tmp_dates[dd] = [[d - dt, d] for d in dates] tmp_files[dd] = len(tmp_dates[dd]) * [file] else: tmp_dates[dd] = [[dd.to_pydatetime(), datetime.datetime(dd.year + 1, 1, 1)]] tmp_files[dd] = [file] # Fetch to datavect f = list_files_avail[indout] target_file = f"{target_dir}/{os.path.basename(f)}" path.link(f, target_file) return tmp_files, tmp_dates