diff --git a/message_ix_models/tools/costs/config.py b/message_ix_models/tools/costs/config.py index 91e33781c1..47eb0d9f4d 100644 --- a/message_ix_models/tools/costs/config.py +++ b/message_ix_models/tools/costs/config.py @@ -1,3 +1,6 @@ +from dataclasses import dataclass +from typing import Literal, Optional + BASE_YEAR = 2021 ADJ_BASE_YEAR = 2020 FIRST_MODEL_YEAR = 2020 @@ -11,3 +14,53 @@ # Conversion rate from 2021 USD to 2005 USD # Taken from https://www.officialdata.org/us/inflation/2021?endYear=2005&amount=1 CONVERSION_2021_TO_2005_USD = 0.72 + + +@dataclass +class Config: + """Configuration for :mod:`.costs`.""" + + #: Base year for projections. + base_year: int = BASE_YEAR + + #: Year of convergence; used when :attr:`.method` is "convergence". See + #: :func:`.create_projections_converge`. + convergence_year: int = 2050 + + #: Rate of increase/decrease of fixed operating and maintenance costs. + fom_rate: float = 0.025 + + #: Format of output. One of: + #: + #: - "iamc": IAMC time series data structure. + #: - "message": :mod:`message_ix` parameter data. + format: Literal["iamc", "message"] = "message" + + #: Spatial resolution + node: Literal["R11", "R12", "R20"] = "R12" + + #: Projection method; one of: + #: + #: - "convergence": uses :func:`.create_projections_converge` + #: - "gdp": :func:`.create_projections_gdp` + #: - "learning": :func:`.create_projections_converge` + method: Literal["convergence", "gdp", "learning"] = "gdp" + + #: Model variant to prepare data for. + module: Literal["base", "materials"] = "base" + + #: Reference region; default "{node}_NAM". + ref_region: Optional[str] = None + + #: Set of SSPs referenced by :attr:`scenario`. One of: + #: + #: - "original": :obj:`SSP_2017` + #: - "updated": :obj:`SSP_2024` + scenario_version: Literal["original", "updated"] = "updated" + + #: Scenario(s) for which to create data. + scenario: Literal["all", "LED", "SSP1", "SSP2", "SSP3", "SSP4", "SSP5"] = "all" + + def __post_init__(self): + if self.ref_region is None: + self.ref_region = f"{self.node}_NAM" diff --git a/message_ix_models/util/config.py b/message_ix_models/util/config.py index 0c48fe467c..8b45ab641e 100644 --- a/message_ix_models/util/config.py +++ b/message_ix_models/util/config.py @@ -97,7 +97,9 @@ def read_file(self, path: Path, fail="raise") -> None: # Use name manipulation on the attribute value also value = existing.replace(**value) elif not isinstance(existing, type): - value = replace(existing, **value) + # https://github.com/python/mypy/issues/15843 + # TODO Check that fix is available in mypy 1.7.x; remove + value = replace(existing, **value) # type: ignore [misc] setattr(self, key, value) def replace(self, **kwargs):