Source code for pycif.plugins.datastreams.fluxes.CAMSREG_nc.utils
import datetime
import glob
from logging import debug, info, warn
import os
import calendar
from pathlib import Path
import numpy as np
from logging import info
from .....utils.check.errclass import CifError
[docs]
def find_valid_file(ref_dir, file_format, dd, ref_dir_next, ref_dir_previous=False):
"""Find the pair of files bracketing a reference date.
Lists the files in ``ref_dir`` (and, when ``dd`` falls near a month
boundary, in ``ref_dir_next``/``ref_dir_previous``) that match
``file_format``, parses their date from the file name, sorts them, and
returns the nearest available file/date before ``dd`` and the nearest
one after ``dd`` (used to bracket forecast-style files).
Args:
ref_dir (str): directory to search for candidate files.
file_format (str): strptime/strftime-compatible file name pattern
used both to parse each candidate file's date and to derive
``dd``'s canonical file name.
dd (datetime.datetime): reference date to bracket.
ref_dir_next (str): adjacent directory to also search when ``dd`` is
close to the end of its month.
ref_dir_previous (str or bool): adjacent directory to also search
when ``dd`` is close to the start of its month; ``False`` to
skip this lookup.
Returns:
(list[str], list[datetime.datetime]): a 2-element list of file paths
``[file_before, file_after]`` and the corresponding 2-element list of
dates ``[date_before, date_after]`` bracketing ``dd``.
Raises:
CifError: if no file matching ``file_format`` is found in
``ref_dir`` (and adjacent directories, if searched).
"""
# Get all files and dates matching the file and format
list_files_orig = os.listdir(ref_dir)
# Convert ref date
ref_date = datetime.datetime.strptime(dd.strftime(file_format), file_format)
previous_date = ref_date - datetime.timedelta(hours=3)
if previous_date.month < ref_date.month and ref_dir_previous:
try:
list_files_orig += os.listdir(ref_dir_previous)
except:
info(f"Did not find any valid files in {ref_dir_previous} with format {file_format}")
next_date = ref_date + datetime.timedelta(hours=3)
if next_date.month > ref_date.month:
try:
list_files_orig += os.listdir(ref_dir_next)
except:
info(f"Did not find any valid files in {ref_dir_previous} with format {file_format}")
list_dates_cur = []
list_files_cur = []
for f in list_files_orig:
try:
if f.find('idx') < 0:
list_dates_cur.append(
datetime.datetime.strptime(f, file_format))
list_files_cur.append(f)
except:
continue
list_files = np.array(list_files_cur)
list_dates = np.array(list_dates_cur)
# Sorting along dates
isort = np.argsort(list_dates)
list_dates = list_dates[isort]
list_files = list_files[isort]
if len(list_files) == 0:
raise CifError(f"Did not find any valid files in '{ref_dir}' with format '{file_format}'. Please check your yml file")
# Compute deltas
mask = (list_dates - ref_date) <= datetime.timedelta(0)
if not np.any(mask):
warn(f"Did not find any date in '{list_dates}' starting before {ref_date} for the available files found: '{list_files}'."
)
warn(f"Assuming the first date {list_dates[0]} is valid already since {ref_date}.")
# Choose the last date and file
file_ref1 = Path(ref_dir, list_files[0])
date_ref1 = list_dates[0]
else:
# find nearest previous date
file_ref1 = Path(ref_dir, list_files[mask][np.argmax(list_dates[mask])])
date_ref1 = list_dates[mask].max()
mask = (list_dates - ref_date) >= datetime.timedelta(0)
if not np.any(mask):
warn(f"Did not find any date in '{list_dates}' starting after {ref_date} for the available files found: '{list_files}'."
)
warn(f"Assuming the last date {list_dates[-1]} is valid until {ref_date}.")
# Choose the last date and file
file_ref2 = Path(ref_dir, list_files[-1])
date_ref2 = list_dates[-1]
else:
# find nearest next date
file_ref2 = Path(ref_dir, list_files[mask][np.argmin(list_dates[mask])])
date_ref2 = list_dates[mask].min()
# Reconvert to original date
dd1 = dd + (date_ref1 - ref_date)
dd2 = dd + (date_ref2 - ref_date)
return [str(file_ref1), str(file_ref2)], [dd1, dd2]