Source code for rook.utils.decadal_fixes

from rook.utils.fixes_utils import convert_calendar_to_gregorian

from rook.utils.data_utils.attr_utils import (
    edit_global_attrs,
    edit_var_attrs,
)
from rook.utils.data_utils.coord_utils import add_coord, add_scalar_coord
from rook.utils.data_utils.var_utils import add_data_var

model_specific_global_attrs = {
    "CMCC-CM2-SR5": {
        "forcing_description": "f1, CMIP6 historical forcings",
        "physics_description": "physics from the standard model configuration, with no additional tuning or different parametrization",  # noqa
        "initialization_description": "hindcast initialized based on observations and using historical forcing",  # noqa
    },
    "EC-Earth3": {
        "forcing_description": "f1, CMIP6 historical forcings",
        "physics_description": "physics from the standard model configuration, with no additional tuning or different parametrization",  # noqa
        "initialization_description": "Atmosphere initialization based on full-fields from ERA-Interim (s1979-s2018) or ERA-40 (s1960-s1978); ocean/sea-ice initialization based on full-fields from NEMO/LIM assimilation run nudged towards ORA-S4 (s1960-s2018)",  # noqa
    },
    "HadGEM3-GC31-MM": {
        "forcing_description": "f2, CMIP6 v6.2.0 forcings; no ozone remapping",
        "physics_description": "physics from the standard model configuration, with no additional tuning or different parametrization",  # noqa
        "initialization_description": "hindcast initialized based on observations and using historical forcing",  # noqa
    },
    "MPI-ESM1-2-HR": {
        "forcing_description": "f1, CMIP6 historical forcings",
        "physics_description": "physics from the standard model configuration, with no additional tuning or different parametrization",  # noqa
        "initialization_description": "hindcast initialized based on observations and using historical forcing",  # noqa
    },
    "MPI-ESM1-2-LR": {
        "forcing_description": "f1, CMIP6 historical forcings",
        "physics_description": "physics from the standard model configuration, with no additional tuning or different parametrization",  # noqa
        "initialization_description": "hindcast initialized based on observations and using historical forcing",  # noqa
    },
}


[docs] def get_decadal_model_attr_from_dict(ds_id, ds, attr): # TODO: method originally ported from legacy decadal utility code. # Add the model-specific global attr model = ds_id.split(".")[3] value = model_specific_global_attrs[model][attr] return value
[docs] def apply_decadal_fixes(ds_id, ds, output_dir=None): ds_mod = decadal_fix_calendar(ds_id, ds, output_dir=output_dir) ds_mod = decadal_fix_1(ds_id, ds_mod) ds_mod = decadal_fix_2(ds_id, ds_mod) ds_mod = decadal_fix_3(ds_id, ds_mod) ds_mod = decadal_fix_4(ds_id, ds_mod) ds_mod = decadal_fix_5(ds_id, ds_mod) return ds_mod
[docs] def decadal_fix_1(ds_id, ds): operands = {"var_id": "time", "attrs": {"long_name": "valid_time"}} ds_mod = edit_var_attrs(ds_id, ds, **operands) return ds_mod
[docs] def decadal_fix_2(ds_id, ds): operands = { "attrs": { "forcing_description": get_decadal_model_attr_from_dict( ds_id, ds, "forcing_description" ), # noqa "physics_description": get_decadal_model_attr_from_dict( ds_id, ds, "physics_description" ), # noqa "initialization_description": get_decadal_model_attr_from_dict( ds_id, ds, "initialization_description" ), # noqa "startdate": "derive: rook.utils.decadal_utils.get_sub_experiment_id", "sub_experiment_id": "derive: rook.utils.decadal_utils.get_sub_experiment_id", } } ds_mod = edit_global_attrs(ds_id, ds, **operands) return ds_mod
[docs] def decadal_fix_3(ds_id, ds): operands = { "var_id": "reftime", "value": "derive: rook.utils.decadal_utils.get_reftime", "dtype": "datetime64[ns]", "attrs": { "long_name": "Start date of the forecast", "standard_name": "forecast_reference_time", }, "encoding": { "dtype": "int32", "units": "days since 1850-01-01", "calendar": "derive: rook.utils.decadal_utils.get_time_calendar", }, } ds_mod = add_scalar_coord(ds_id, ds, **operands) return ds_mod
[docs] def decadal_fix_4(ds_id, ds): operands = { "var_id": "leadtime", "value": "derive: rook.utils.decadal_utils.get_lead_times", "dim": ["time"], "dtype": "float64", "attrs": { "long_name": "Time elapsed since the start of the forecast", "standard_name": "forecast_period", "units": "days", }, "encoding": {"dtype": "double"}, } ds_mod = add_coord(ds_id, ds, **operands) return ds_mod
[docs] def decadal_fix_5(ds_id, ds): operands = { "var_id": "realization", "value": ds.attrs.get("realization_index"), "dtype": "int32", "attrs": { "long_name": "realization", "comment": "For more information on the ripf, refer to the variant_label, initialization_description, physics_description and forcing_description global attributes", # noqa }, } ds_mod = add_data_var(ds_id, ds, **operands) return ds_mod
[docs] def decadal_fix_calendar(ds_id, ds, output_dir=None): # set proleptic_gregorian calendar to gregorian (standard). # the proleptic gregorian calendar extends the gregorin backward in time before 1582. calendar = ds.time.encoding.get("calendar", "standard") if calendar == "proleptic_gregorian": # ds.time.encoding["calendar"] = "standard" ds = convert_calendar_to_gregorian(ds) return ds