Source code for smif.metadata.timestep

"""smif runs models over a series of planning timesteps.

:class:`~smif.metadata.timestep.RelativeTimestep` is used to specify one timestep relative to
another in the context of the set of planning timesteps.

For example, if a model needs to know its own outputs from a previous year, we can specify the
self-dependency using a relative timestep.
"""
from enum import Enum
from typing import List, Union

from smif.exception import SmifTimestepResolutionError


[docs]class RelativeTimestep(Enum): """Specify current, previous or base year timestep """ CURRENT = 'CURRENT' # current planning timestep PREVIOUS = 'PREVIOUS' # previous planning timestep BASE = 'BASE' # base year planning timestep ALL = 'ALL' # all planning timesteps
[docs] @classmethod def from_name(cls, name): if name == 'CURRENT': return cls.CURRENT elif name == 'PREVIOUS': return cls.PREVIOUS elif name == 'BASE': return cls.BASE elif name == 'ALL': return cls.ALL raise ValueError("Relative timestep '%s' is not recognised" % name)
[docs] def resolve_relative_to(self, timestep: int, timesteps: List[int]) -> Union[None, int]: """Resolve a relative timestep with respect to a given timestep and sequence of timesteps. Parameters ---------- timestep : int timesteps : list of int """ if timestep not in timesteps: raise SmifTimestepResolutionError( "Timestep {} is not present in {}".format(timestep, timesteps)) # default None, e.g. for ALL relative_timestep = None if self.name == 'CURRENT': relative_timestep = timestep elif self.name == 'PREVIOUS': try: relative_timestep = element_before(timestep, timesteps) except ValueError: raise SmifTimestepResolutionError( "{} has no previous timestep in {}".format(timestep, timesteps)) elif self.name == 'BASE': relative_timestep = timesteps[0] return relative_timestep
[docs]def element_before(element: int, list_: List[int]) -> int: """Return the element before a given element in a list, or None if the given element is first or not in the list. """ if element not in list_ or element == list_[0]: raise ValueError("No element before {} in {}".format(element, list_)) else: index = list_.index(element) return list_[index - 1]