Source code for message_ix_models.util.scenarioinfo

""":class:`ScenarioInfo` class."""
from collections import defaultdict
from itertools import product
from typing import Dict, List

import pandas as pd


[docs]class ScenarioInfo: """Information about a :class:`~message_ix.Scenario` object. Code that prepares data for a target Scenario can accept a ScenarioInfo instance. This avoids any need to load a Scenario, which can be slow under some conditions. ScenarioInfo objects are also used by :func:`.apply_spec` to describe the contents of a scenario before it is created. ScenarioInfo objects have the following attributes: .. autosummary:: set is_message_macro N Y y0 yv_ya """ #: Elements of :mod:`ixmp`/:mod:`message_ix` sets in the Scenario. set: Dict[str, List] = {} #: First model year, if set, else ``Y[0]``. y0: int = -1 #: :obj:`True` if a MESSAGE-MACRO scenario. is_message_macro: bool = False _yv_ya: pd.DataFrame = None def __init__(self, scenario=None): self.set = defaultdict(list) if not scenario: return for name in scenario.set_list(): try: self.set[name] = scenario.set(name).tolist() except AttributeError: continue # pd.DataFrame for ≥2-D set; don't convert self.is_message_macro = "PRICE_COMMODITY" in scenario.par_list() # Computed once fmy = scenario.cat("year", "firstmodelyear") self.y0 = int(fmy[0]) if len(fmy) else self.set["year"][0] self._yv_ya = scenario.vintage_and_active_years() @property def yv_ya(self): """(year_vtg, year_act) for the entire model horizon.""" if self._yv_ya is None: first = self.y0 # Product of all years yv = ya = self.set["year"] # Predicate for filtering years def _valid(elem): yv, ya = elem return first <= yv <= ya # - Cartesian product of all yv and ya. # - Filter only valid years. # - Convert to data frame. self._yv_ya = pd.DataFrame( filter(_valid, product(yv, ya)), columns=["year_vtg", "year_act"] ) return self._yv_ya @property def N(self): """Elements of the set 'node'.""" return list(map(str, self.set["node"])) @property def Y(self): """Elements of the set 'year' that are >= the first model year.""" return list(filter(lambda y: y >= self.y0, self.set["year"]))