Source code for pycif.plugins.datastreams.fields.lmdz_chemfield_reg.fetch

from __future__ import annotations

import datetime
import os
from os import PathLike
from pathlib import Path

import pandas as pd

from .....utils import path
from .....utils.check.errclass import CifFileNotFoundError


# pylint: disable=unused-argument
[docs] def fetch( ref_dir: str | PathLike, ref_file: str | PathLike, input_interval: tuple[datetime.datetime, datetime.datetime], target_dir: str | PathLike, tracer: object | None = None, **kwargs, ) -> tuple[ dict[datetime.datetime, list[str | PathLike]], dict[datetime.datetime, list[tuple[datetime.datetime, datetime.datetime]]], ]: """Link monthly LMDz chemical field files and build daily sub-intervals. Builds the list of monthly file dates spanning ``input_interval`` at ``tracer.file_freq``, links each file into ``target_dir`` (raising if a file is missing), and for each linked file generates one daily ``[start, end]`` sub-interval per day of that month. Args: ref_dir: Directory where the original files are found. If both ``ref_dir`` and ``ref_file`` are falsy, nothing is fetched. ref_file: Date-format pattern for the original file names. input_interval: Tuple of two dates, the beginning and end of the period to fetch. target_dir: Directory where links to the original files are created. tracer: Tracer/component configuration; ``tracer.file_freq`` gives the frequency at which files are available. **kwargs: Unused. Returns: A tuple ``(list_files, list_dates)`` of dictionaries keyed by monthly file date. ``list_dates`` maps each key to one ``(day_start, day_end)`` interval per day of the month; ``list_files`` maps each key to the (repeated) path of that month's file. Raises: CifFileNotFoundError: If an expected monthly file does not exist. """ if not ref_dir and not ref_file: return {}, {} # Reshape input interval to include full months date_i, date_f = input_interval file_freq = tracer.file_freq # type: ignore # Getting file dates file_dates = pd.date_range(date_i, date_f, freq=file_freq, inclusive="left") if file_dates.empty: file_dates = pd.to_datetime([date_i]) if file_dates[0] > date_i: file_dates = pd.to_datetime([date_i] + file_dates.to_list()) # Getting files paths file_paths = [Path(ref_dir, date.strftime(ref_file)) for date in file_dates] list_dates = {} list_files = {} for date, source_path in zip(file_dates, file_paths): if not source_path.is_file(): raise CifFileNotFoundError(f"file '{source_path}' not found") # Fetching target_path = os.path.join(target_dir, os.path.basename(source_path)) path.link(source_path, target_path) # Timestamps (assume monthly files with daily resolution) period_start = pd.date_range(date, periods=date.days_in_month, freq="1D") period_end = period_start + pd.offsets.Hour(24) # pylint: disable=no-member date = date.to_pydatetime() period_start = period_start.to_pydatetime() # type: ignore period_end = period_end.to_pydatetime() list_dates[date] = list(zip(period_start, period_end)) list_files[date] = len(period_start) * [str(target_path)] return list_files, list_dates