Source code for lories.system

# -*- coding: utf-8 -*-
"""
lories.system
~~~~~~~~~~~~~


"""

from __future__ import annotations

import os
from typing import Any, List, Optional

import pandas as pd
from lories import Configurations
from lories.components import Component, ComponentContext, ComponentUnavailableError, Weather
from lories.core.typing import Timestamp
from lories.location import Location, LocationUnavailableException
from lories.simulation import Results


[docs] class System(Component): TYPE: str = "system" _location: Optional[Location] = None @classmethod def scan(cls, context: ComponentContext, scan_dir: str, **kwargs) -> List[System]: systems = [] for system_dir in os.scandir(scan_dir): if os.path.isdir(system_dir.path): kwargs["data_dir"] = system_dir.path systems.append(cls.load(context, **kwargs)) return systems # noinspection PyProtectedMember @classmethod def load(cls, context: ComponentContext, **kwargs) -> System: configs = Configurations.load(f"{cls.__name__.lower()}.conf", **kwargs) system_id = cls._build_id(context=context, configs=configs) if context._contains(system_id): context._update(system_id, configs) system = context._get(system_id) else: system = cls(context=context, configs=configs, id=system_id) context._add(system) return system # noinspection PyShadowingBuiltins, PyUnusedLocal def __init__( self, context: ComponentContext = None, configs: Optional[Configurations] = None, id: Optional[str] = None, key: Optional[str] = None, name: Optional[str] = None, **kwargs, ) -> None: name = self._build_name(name, configs=configs) key = self._build_key(key, configs=configs) id = self._build_id(id, key, configs=configs, context=context) super().__init__( context=context, configs=configs, id=id, key=key, name=name, **kwargs, ) def configure(self, configs: Configurations) -> None: super().configure(configs) self.localize(configs.get_member(Location.TYPE, defaults={})) self.components.load(configs_dir=self.configs.dirs.conf) def localize(self, configs: Configurations) -> None: if configs.enabled and all(k in configs for k in ["latitude", "longitude"]): self._location = Location( configs.get_float("latitude"), configs.get_float("longitude"), timezone=configs.get("timezone", default="UTC"), altitude=configs.get_float("altitude", default=None), country=configs.get("country", default=None), state=configs.get("state", default=None), ) else: self._location = None def is_localized(self) -> bool: return self._location is not None @property def location(self) -> Location: if self._location is None: raise LocationUnavailableException(f"System '{self.name}' has no location configured") return self._location def has_weather(self) -> bool: return self.components.has_type(Weather) # noinspection PyTypeChecker @property def weather(self) -> Weather: weather = self.components.get_first(Weather) if weather is None: raise ComponentUnavailableError(f"System '{self.name}' has no weather configured") return weather def simulate( self, start: Timestamp, end: Timestamp, prior: Optional[pd.DataFrame] = None, **kwargs: Any, ) -> pd.DataFrame: raise NotImplementedError() def evaluate(self, results: Results) -> pd.DataFrame: raise NotImplementedError()