Source code for energia.dimensions.space
"""Space"""
from dataclasses import dataclass
from .._core._dimension import _Dimension
from ..components.spatial.linkage import Linkage
from ..components.spatial.location import Location
[docs]
@dataclass
class Space(_Dimension):
"""
Spatial representation of the system.
All spatial components are attached to this object.
:param model: Model to which the representation belongs.
:type model: Model
:ivar name: Name of the dimension, auto generated
:vartype name: str
:ivar locations: List of locations in the space.
:vartype locations: list[Loc]
:ivar sources: List of source locations.
:vartype sources: list[Loc]
:ivar sinks: List of sink locations.
:vartype sinks: list[Loc]
:ivar linkages: List of linkages in the space.
:vartype linkages: list[Link]
:ivar label: Label for the space.
:vartype label: str
:ivar default: Default location for the space. Defaults to None.
:vartype default: Loc
:ivar network: The encompassing region (network) of the space.
:vartype network: Loc
:ivar s: List of spatial components (locations and linkages).
:vartype s: list[Loc | Link]
:ivar tree: Nested dictionary of locations.
:vartype tree: dict
:ivar hierarchy: position on tree.
:vartype hierarchy: dict[int, list[Loc]]
.. note::
- name is self generated
- locations, sources, sinks, and linkages are populated as model is defined
- label is fixed
- default is set to None initially and is updated when needed (see network property)
"""
def __post_init__(self):
self.locations: list[Location] = []
self.sources: list[Location] = []
self.sinks: list[Location] = []
self.linkages: list[Linkage] = []
_Dimension.__post_init__(self)
# -----------------------------------------------------
# Helpers
# -----------------------------------------------------
@property
def tree(self) -> dict:
"""creates a nested dictionary of locations"""
tree_ = {self.network: {}}
for loc in self.network.has:
tree_[self.network][loc] = loc.tree
return tree_
@property
def hierarchy(self) -> dict[int, list[Location]]:
"""gives position in tree"""
self.network.update_hierarchy()
hierarchy_ = {}
for spc in self.s:
if spc.hierarchy not in hierarchy_:
hierarchy_[spc.hierarchy] = []
hierarchy_[spc.hierarchy].append(spc)
return hierarchy_
@property
def not_nested(self) -> list[Location]:
"""List of locations that are not nested under another location"""
return [loc for loc in self.locations if not loc.isin]
# -----------------------------------------------------
# Superlative
# -----------------------------------------------------
def _ntw_from_not_nested(self) -> Location:
"""
Make a location to be held as network
Using all existing non-nested locations
"""
# property, make it do the work only once
not_nested = self.not_nested
if len(not_nested) == 1:
# only one implies that all locations are nested under the one location
return not_nested[0]
# sum up all not nested locations to make a network
ntw = sum(not_nested)
setattr(self.model, "ntw", ntw)
return ntw
@property
def network(self) -> Location:
"""An encompassing location"""
# if no location is available, create a default one
if not self.locations:
return self.model._l0()
# if only one location is available, return it
if len(self.locations) == 1:
return self.locations[0]
return self._ntw_from_not_nested()
@property
def s(self) -> list[Location | Linkage]:
"""List of spatial components"""
return self.locations + self.linkages
def _lower(
self, loc: Location, hierarchy: dict[int, list[Location]]
) -> list[Location]:
"""Return all locations at lower hierarchy than loc"""
if loc.hierarchy + 1 in hierarchy:
return [lc for lc in hierarchy[loc.hierarchy + 1] if lc in loc.has]
return []
def _upper(
self, loc: Location, hierarchy: dict[int, list[Location]]
) -> Location | None:
"""Return Location at higher hierarchy than loc"""
try:
return [lc for lc in hierarchy[loc.hierarchy - 1] if loc in lc.has][0]
except IndexError:
return None
[docs]
def split(self, loc: Location) -> tuple[list[Location], Location | None]:
"""Gives a list of locations at a higher and lower hierarchy than loc"""
# hierarchy is a property
# we want it at this stage
hierarchy = self.hierarchy
return self._lower(loc, hierarchy), self._upper(loc, hierarchy)