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]