Skip to content

Commit

Permalink
Do method placement, read_study_service method, and some tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
killian-scalian committed Sep 13, 2024
1 parent 6e77698 commit 599b93f
Show file tree
Hide file tree
Showing 8 changed files with 409 additions and 10 deletions.
68 changes: 58 additions & 10 deletions src/antares/model/study.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from antares.model.settings import StudySettings
from antares.service.api_services.study_api import _returns_study_settings
from antares.service.base_services import BaseStudyService
from antares.service.service_factory import ServiceFactory
from antares.service.service_factory import ServiceFactory, ServiceReader

"""
The study module defines the data model for antares study.
Expand Down Expand Up @@ -77,6 +77,15 @@ def _verify_study_already_exists(study_directory: Path) -> None:
raise FileExistsError(f"Study {study_directory} already exists.")


def _directories_can_be_read(local_path: Path) -> None:
if local_path.is_dir():
try:
for item in local_path.iterdir():
if item.is_dir():
next(item.iterdir())
except PermissionError:
raise PermissionError(f"Some content cannot be accessed in {local_path}")

def create_study_local(
study_name: str, version: str, local_config: LocalConfiguration, settings: Optional[StudySettings] = None
) -> "Study":
Expand Down Expand Up @@ -142,23 +151,62 @@ def _directory_not_exists(local_path: Path) -> None:
version=version,
service_factory=ServiceFactory(config=local_config, study_name=study_name),
settings=settings,
mode="create",
)


def read_study_local(
study_name: str, version: str, local_config: LocalConfiguration) -> "Study":
"""
Create a directory structure for the study with empty files.
Args:
study_name: antares study name to read
version: antares version for study
settings: study settings. If not provided, AntaresWeb will use its default values.
Raises:
PermissionError if the study cannot be read
ValueError if the provided directory does not exist
"""
def _directory_not_exists(local_path: Path) -> None:
if local_path is None or not os.path.exists(local_path):
raise ValueError(f"Provided directory {local_path} does not exist.")

_directory_not_exists(local_config.local_path)
study_directory = local_config.local_path / study_name
_directories_can_be_read(study_directory)

return Study(
name=study_name,
version=version,
service_factory=ServiceReader(config=local_config, study_name=study_name),
mode="read",
)


class Study:
def __init__(
self, name: str, version: str, service_factory: ServiceFactory, settings: Optional[StudySettings] = None
self, name: str, version: str, service_factory, settings: Optional[StudySettings] = None, mode: str = "create"
):
self.name = name
self.version = version
self._study_service = service_factory.create_study_service()
self._area_service = service_factory.create_area_service()
self._link_service = service_factory.create_link_service()
self._binding_constraints_service = service_factory.create_binding_constraints_service()
self._settings = settings or StudySettings()
self._areas: Dict[str, Area] = dict()
self._links: Dict[str, Link] = dict()
self._binding_constraints: Dict[str, BindingConstraint] = dict()
if mode != "read":
self._study_service = service_factory.create_study_service()
self._area_service = service_factory.create_area_service()
self._link_service = service_factory.create_link_service()
self._binding_constraints_service = service_factory.create_binding_constraints_service()
self._settings = settings or StudySettings()
self._areas: Dict[str, Area] = dict()
self._links: Dict[str, Link] = dict()
self._binding_constraints: Dict[str, BindingConstraint] = dict()
else:
self._study_service = service_factory.read_study_service()
self._binding_constraints: Dict[str, BindingConstraint] = dict()
self._link_service = service_factory.create_link_service()
self._areas: Dict[str, Area] = dict()
self._links: Dict[str, Link] = dict()


@property
def service(self) -> BaseStudyService:
Expand Down
119 changes: 119 additions & 0 deletions src/antares/service/base_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,73 @@ def get_load_matrix(self, area: Area) -> pd.DataFrame:
# Once it will, there will be no change to do in the code on our side.
pass

@abstractmethod
def read_thermal_cluster(
self,
area_id: str,
thermal_name: str,
properties: Optional[ThermalClusterProperties] = None,
) -> ThermalCluster:
pass


@abstractmethod
def read_renewable_cluster(
self,
area_id: str,
renewable_name: str,
properties: Optional[RenewableClusterProperties] = None,
series: Optional[pd.DataFrame] = None,
) -> RenewableCluster:
pass

@abstractmethod
def read_st_storage(
self, area_id: str, st_storage_name: str, properties: Optional[STStorageProperties] = None
) -> STStorage:
pass

@abstractmethod
def read_wind(self, area: Area, series: Optional[pd.DataFrame]) -> Wind:
pass

@abstractmethod
def read_reserves(self, area: Area, series: Optional[pd.DataFrame]) -> Reserves:
pass

@abstractmethod
def read_solar(self, area: Area, series: Optional[pd.DataFrame]) -> Solar:
pass

@abstractmethod
def read_misc_gen(self, area: Area, series: Optional[pd.DataFrame]) -> MiscGen:
pass

@abstractmethod
def read_hydro(
self,
area_id: str,
properties: Optional[HydroProperties] = None,
matrices: Optional[Dict[HydroMatrixName, pd.DataFrame]] = None,
) -> Hydro:
pass

@abstractmethod
def read_area(
self, area_name: str, properties: Optional[AreaProperties] = None, ui: Optional[AreaUi] = None
) -> Area:
"""
Args:
area_name: area to be added to study
properties: area's properties. If not provided, default values will be used.
ui: area's ui characteristics. If not provided, default values will be used.
Returns: area name if success or Error if area can not be
created
"""

pass


class BaseLinkService(ABC):
@abstractmethod
Expand Down Expand Up @@ -317,6 +384,28 @@ def update_link_ui(self, link: Link, ui: LinkUi) -> LinkUi:
"""
pass

@abstractmethod
def read_link(
self,
area_from: Area,
area_to: Area,
properties: Optional[LinkProperties] = None,
ui: Optional[LinkUi] = None,
existing_areas: Optional[MappingProxyType[str, Area]] = None,
) -> Link:
"""
Args:
area_from: area where the link goes from
area_to: area where the link goes to
properties: link's properties
ui: link's ui characteristics
existing_areas: existing areas from study
Returns:
The created link
"""
pass


class BaseThermalService(ABC):
@abstractmethod
Expand Down Expand Up @@ -421,6 +510,30 @@ def update_constraint_matrix(
"""
pass

@abstractmethod
def read_binding_constraint(
self,
name: str,
properties: Optional[BindingConstraintProperties] = None,
terms: Optional[List[ConstraintTerm]] = None,
less_term_matrix: Optional[pd.DataFrame] = None,
equal_term_matrix: Optional[pd.DataFrame] = None,
greater_term_matrix: Optional[pd.DataFrame] = None,
) -> BindingConstraint:
"""
Args:
name: the binding constraint name
properties: the properties of the constraint. If not provided, AntaresWeb will use its own default values.
terms: the terms of the constraint. If not provided, no term will be created.
less_term_matrix: matrix corresponding to the lower bound of the constraint. If not provided, no matrix will be created.
equal_term_matrix: matrix corresponding to the equality bound of the constraint. If not provided, no matrix will be created.
greater_term_matrix: matrix corresponding to the upper bound of the constraint. If not provided, no matrix will be created.
Returns:
The created binding constraint
"""
pass


class BaseStudyService(ABC):
@property
Expand Down Expand Up @@ -458,6 +571,12 @@ def delete(self, children: bool) -> None:
"""
pass

@abstractmethod
def read_areas(self) -> None:
"""
Read areas
"""
pass

class BaseRenewableService(ABC):
@abstractmethod
Expand Down
111 changes: 111 additions & 0 deletions src/antares/service/local_services/area_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,114 @@ def upload_load_matrix(self, area: Area, load_matrix: pd.DataFrame) -> None:

def get_load_matrix(self, area: Area) -> pd.DataFrame:
raise NotImplementedError

def read_thermal_cluster(
self,
area_id: str,
thermal_name: str,
properties: Optional[ThermalClusterProperties] = None,
) -> ThermalCluster:
local_thermal_properties = ThermalClusterPropertiesLocal(thermal_name, properties)

list_ini = IniFile(self.config.study_path, IniFileTypes.THERMAL_LIST_INI, area_name=area_id)
list_ini.add_section(local_thermal_properties.list_ini_fields)
list_ini.write_ini_file(sort_sections=True)

return ThermalCluster(
self.thermal_service, area_id, thermal_name, local_thermal_properties.yield_thermal_cluster_properties()
)


def read_renewable_cluster(
self,
area_id: str,
renewable_name: str,
properties: Optional[RenewableClusterProperties] = None,
) -> RenewableCluster:
local_properties = RenewableClusterPropertiesLocal(renewable_name, properties)

list_ini = IniFile(self.config.study_path, IniFileTypes.RENEWABLES_LIST_INI, area_name=area_id)
list_ini.add_section(local_properties.ini_fields)
list_ini.write_ini_file()

return RenewableCluster(
self.renewable_service, area_id, renewable_name, local_properties.yield_renewable_cluster_properties()
)

def read_st_storage(
self, area_id: str, st_storage_name: str, properties: Optional[STStorageProperties] = None
) -> STStorage:
local_st_storage_properties = STStoragePropertiesLocal(st_storage_name, properties)

list_ini = IniFile(self.config.study_path, IniFileTypes.ST_STORAGE_LIST_INI, area_name=area_id)
list_ini.add_section(local_st_storage_properties.list_ini_fields)
list_ini.write_ini_file(sort_sections=True)

return STStorage(
self.storage_service,
area_id,
st_storage_name,
local_st_storage_properties.yield_st_storage_properties(),
)

def read_wind(self, area: Area) -> Wind:
series = pd.DataFrame([])
local_file = TimeSeriesFile(TimeSeriesFileType.WIND, self.config.study_path, area.id, series)
return Wind(series, local_file)

def read_reserves(self, area: Area) -> Reserves:
series = pd.DataFrame([])
local_file = TimeSeriesFile(TimeSeriesFileType.RESERVES, self.config.study_path, area.id, series)
return Reserves(series, local_file)

def read_solar(self, area: Area) -> Solar:
series = pd.DataFrame([])
local_file = TimeSeriesFile(TimeSeriesFileType.SOLAR, self.config.study_path, area.id, series)
return Solar(series, local_file)

def read_misc_gen(self, area: Area, series: Optional[pd.DataFrame]) -> MiscGen:
series = series if series is not None else pd.DataFrame([])
local_file = TimeSeriesFile(TimeSeriesFileType.MISC_GEN, self.config.study_path, area.id, series)
return MiscGen(series, local_file)

def read_hydro(
self,
area_id: str,
properties: Optional[HydroProperties] = None,
) -> Hydro:
local_hydro_properties = HydroPropertiesLocal(area_id, properties)

list_ini = IniFile(self.config.study_path, IniFileTypes.HYDRO_INI)
list_ini.add_section(local_hydro_properties.hydro_ini_fields)
list_ini.write_ini_file(sort_section_content=True)

return Hydro(self, area_id, local_hydro_properties.yield_hydro_properties())

def read_area(
self, area_name: str, area_id: str) -> Area:
"""
Args:
area_name: area to be added to study
area_id: area id. If not provided, default values will be used.
Returns: area object if success or Error if area can not be
read
"""

def _line_exists_in_file(file_content: str, line_to_add: str) -> bool:
"""
Args:
file_content: file content to check
line_to_add: line to add
Returns: True if line is already present in file.
"""
return line_to_add.strip() in file_content.split("\n")


existing_path = self._config.local_path
study_path = existing_path / self.study_name
list_ini = IniFile(self.config.study_path, IniFileTypes.AREAS_SETS_INI)

return {}
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,9 @@ def update_constraint_matrix(
self, constraint: BindingConstraint, matrix_name: ConstraintMatrixName, matrix: pd.DataFrame
) -> None:
raise NotImplementedError

def read_binding_constraint(
self, constraint: BindingConstraint, matrix_name: ConstraintMatrixName, matrix: pd.DataFrame
) -> None:
raise NotImplementedError

22 changes: 22 additions & 0 deletions src/antares/service/local_services/link_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,25 @@ def sort_link_properties_dict(ini_dict: Dict[str, str]) -> Dict[str, str]:
"filter-year-by-year",
]
return dict(sorted(ini_dict.items(), key=lambda item: dict_order.index(item[0])))

def read_link(
self,
area_from: Area,
area_to: Area
) -> Link:
"""
Args:
area_from: area where the link goes from
area_to: area where the link goes to
properties: link's properties
ui: link's ui characteristics
existing_areas: existing areas from study
Returns:
The created link
Raises:
LinkCreationError if an area doesn't exist or existing areas have not been provided
"""
pass

Loading

0 comments on commit 599b93f

Please sign in to comment.