Source code for rameau.core.settings.forecast_settings

# Copyright 2025, BRGM
# 
# This file is part of Rameau.
# 
# Rameau is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
# 
# Rameau is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# Rameau. If not, see <https://www.gnu.org/licenses/>.
#
"""
Forecast settings.
"""

from __future__ import annotations
from typing import Optional, Literal, Union, List

import datetime

from rameau.wrapper import CForecastSettings

from rameau.core._abstract_wrapper import AbstractWrapper
from rameau.core._utils import _check_literal, _set_datetime, _get_datetime
from rameau.core._descriptor import (
     _BoolDescriptor, _VectorDescriptor,
     _DatetimeDescriptor, _TimedeltaDescriptor,
     _StrDescriptor
)

[docs] class ForecastSettings(AbstractWrapper): """ Forecast settings. Parameters ---------- emission_date: `datetime.datetime`, optional The date and time on which to issue a forecast. scope: `datetime.timedelta`, optional The duration for which to run the forecast. If not provided, set to one day. year_members: `list` or `ìnt`, optional The years to consider to form the forecast ensemble members. If not provided, all years in record are considered. correction: `str`, optional The approach to use to correct the initial conditions before issuing the forecast. ================= ========================================= correction description ================= ========================================= ``'no'`` No correction is performed. This is the default behaviour. ``'halflife'`` A correction using the observation of the forecast variable on the issue date is applied and then the correction is gradually dampened overtime based on a half-life parameter. ================= ========================================= pumping_date: `datetime.datetime`, optional The date and time on which to start pumping. quantiles_output: `bool`, optional Whether to reduce the forecast ensemble members to specific climatology quantiles. If not provided, all years in record or years specified via the ``year_members`` parameter are considered. The quantiles can be chosen via the ``quantiles`` parameter. quantiles: `list` or `int`, optional The climatology percentiles to include in the forecast ensemble members. Only considered if ``quantiles_output`` is set to `True`. By default, the percentiles computed are 10, 20, 50, 80, and 90. norain: `bool`, optional Whether to include an extra ensemble member corresponding to a completely rain-free year. By default, this member is not included in the forecast output. Returns ------- `ForecastSettings` """ _computed_attributes = ( "emission_date", "scope", "year_members", "correction", "pumping_date", "quantiles_output", "quantiles", "norain" ) _c_class = CForecastSettings emission_date: datetime.datetime = _DatetimeDescriptor( 0, doc="The date and time on which to issue a forecast." ) #type: ignore pumping_date: datetime.datetime = _DatetimeDescriptor( 1, doc="The date and time on which to start pumping." ) #type: ignore scope: datetime.timedelta = _TimedeltaDescriptor( 0, doc="The duration for which to run the forecast." ) #type: ignore year_members: Union[List[int], tuple[int]] = _VectorDescriptor( 0, int, doc="The years to consider to form the forecast ensemble members." ) #type: ignore quantiles: Union[List[int], tuple[int]] = _VectorDescriptor( 1, int, doc=( "The climatology percentiles to include in " "the forecast ensemble members." ) ) #type: ignore quantiles_output: bool = _BoolDescriptor( 0, doc=( "Whether to reduce the forecast ensemble members " "to specific climatology quantiles." ) ) #type: ignore norain: bool = _BoolDescriptor( 1, doc=( "Whether to include an extra ensemble member corresponding to" "a completely rain-free year." ) ) #type: ignore correction: str = _StrDescriptor( 0, doc=( "The approach to use to correct the initial conditions" "before issuing a forecast." ) ) #type: ignore def __init__( self, emission_date: Optional[datetime.datetime] = None, scope: datetime.timedelta = datetime.timedelta(1), year_members: Optional[Union[List[int], tuple[int]]] = None, correction: Literal["no", "halflife", "enkf"] = "no", pumping_date: Optional[datetime.datetime] = None, quantiles_output: bool = False, quantiles: Union[List[int], tuple[int]] = [10, 20, 50, 80, 90], norain: bool = False ) -> None: self._init_c() if emission_date is not None: self.emission_date = emission_date else: self.emission_date = datetime.datetime(9999, 12, 31) if pumping_date is not None: self.pumping_date = pumping_date else: self.pumping_date = datetime.datetime(9999, 12, 31) self.scope = scope _check_literal( correction, ["no", "halflife", "enkf"] ) self.correction = correction if year_members is not None: if isinstance(year_members, (list, tuple)): self.year_members = year_members else: raise TypeError(f"Type {type(year_members)} not allowed.") self.quantiles_output = quantiles_output if isinstance(quantiles, (list, tuple)): self.quantiles = quantiles else: raise TypeError(f"Type {type(quantiles)} not allowed.") self.norain = norain