Source code for rook.utils.decadal_utils

"""Utility functions for fixing decadal datasets."""

import re
from datetime import datetime

import cftime


[docs] def get_time_calendar(ds_id, ds): """Get the calendar from the dataset time axis.""" times = ds.time.values return times[0].calendar
[docs] def get_start_date(ds_id, ds): """Get start date inferred from decadal dataset id.""" year = ds_id.split(".")[5].split("-")[0].lstrip("s") return datetime(int(year), 11, 1, 0, 0).isoformat()
[docs] def get_sub_experiment_id(ds_id, ds): """Get sub-experiment identifier from start date.""" sd = datetime.fromisoformat(get_start_date(ds_id, ds)) return f"s{sd.year}{sd.month}"
[docs] def get_reftime(ds_id, ds): """Get reference time for decadal forecast.""" default_sd = get_start_date(ds_id, ds) start_date = ds.attrs.get("startdate", None) if not start_date: start_date = default_sd else: regex = re.compile(r"^s(\d{4})(\d{2})$") match = regex.match(start_date) default = datetime.fromisoformat(default_sd) if match: items = match.groups() try: start_date = datetime( int(items[0]), int(items[1]), default.day, default.hour, default.minute, default.second, ).isoformat() except ValueError: start_date = default_sd.isoformat() else: start_date = default_sd.isoformat() return start_date
[docs] def get_lead_times(ds_id, ds): """Get lead times in days relative to forecast reference time.""" start_date = datetime.fromisoformat(get_start_date(ds_id, ds)) cal = get_time_calendar(ds_id, ds) reftime = cftime.datetime( start_date.year, start_date.month, start_date.day, start_date.hour, start_date.minute, start_date.second, calendar=cal, ) lead_times = [] for time in ds.time.values: td = time - reftime lead_times.append(td.days) return lead_times